use nom::{be_u8,IResult,Context,Err,ErrorKind,Needed};
use rusticata_macros::bytes_to_u64;
use der::*;
use error::*;
use oid::Oid;
fn parse_identifier(i: &[u8]) -> IResult<&[u8],(u8,u8,u8)> {
if i.is_empty() { Err(Err::Incomplete(Needed::Size(1))) }
else {
let a = i[0] >> 6;
let b = if i[0] & 0b0010_0000 != 0 {1} else {0};
let c = i[0] & 0b0001_1111;
Ok((&i[1..],(a,b,c)))
}
}
fn parse_der_length_byte(i: &[u8]) -> IResult<&[u8],(u8,u8)> {
if i.is_empty() { Err(Err::Incomplete(Needed::Size(1))) }
else {
let a = i[0] >> 7;
let b = i[0] & 0b0111_1111;
Ok((&i[1..],(a,b)))
}
}
pub fn parse_der_u32(i:&[u8]) -> IResult<&[u8],u32> {
match parse_der_integer(i) {
Ok((rem,ref obj)) => {
match obj.content {
DerObjectContent::Integer(i) => {
match i.len() {
1 => Ok((rem, i[0] as u32)),
2 => Ok((rem, (i[0] as u32) << 8 | (i[1] as u32) )),
3 => Ok((rem, (i[0] as u32) << 16 | (i[1] as u32) << 8 | (i[2] as u32) )),
4 => Ok((rem, (i[0] as u32) << 24 | (i[1] as u32) << 16 | (i[2] as u32) << 8 | (i[3] as u32) )),
_ => Err(Err::Error(error_position!(i, ErrorKind::Custom(DER_INTEGER_TOO_LARGE)))),
}
}
_ => Err(Err::Error(error_position!(i, ErrorKind::Custom(DER_TAG_ERROR)))),
}
}
Err(e) => Err(e)
}
}
pub fn parse_der_u64(i:&[u8]) -> IResult<&[u8],u64> {
match parse_der_integer(i) {
Ok((rem,ref obj)) => {
match obj.content {
DerObjectContent::Integer(i) => {
match bytes_to_u64(i) {
Ok(l) => Ok((rem, l)),
Err(_) => Err(Err::Error(error_position!(i, ErrorKind::Custom(DER_INTEGER_TOO_LARGE)))),
}
}
_ => Err(Err::Error(error_position!(i, ErrorKind::Custom(DER_TAG_ERROR)))),
}
}
Err(e) => Err(e)
}
}
fn der_read_oid(i: &[u8]) -> Result<Vec<u64>,u64> {
let mut oid = Vec::new();
let mut acc : u64;
if i.is_empty() { return Err(0); };
acc = i[0] as u64;
oid.push( acc / 40);
oid.push( acc % 40);
acc = 0;
for &c in &i[1..] {
acc = (acc << 7) | (c & 0b0111_1111) as u64;
if (c & (1<<7)) == 0 {
oid.push(acc);
acc = 0;
}
}
match acc {
0 => Ok(oid),
_ => Err(acc),
}
}
named!(pub der_read_element_header<&[u8],DerObjectHeader>,
do_parse!(
el: parse_identifier >>
len: parse_der_length_byte >>
llen: cond!(len.0 == 1, take!(len.1)) >>
( {
let len : u64 = match len.0 {
0 => len.1 as u64,
_ => {
match bytes_to_u64(llen.unwrap()) {
Ok(l) => l,
Err(_) => { return Err(::nom::Err::Error(error_position!(llen.unwrap(), ErrorKind::Custom(DER_TAG_ERROR)))); },
}
},
};
DerObjectHeader {
class: el.0,
structured: el.1,
tag: el.2,
len,
}
} )
)
);
named!(der_read_sequence_content<&[u8],Vec<DerObject> >,
many0!(complete!(parse_der))
);
named!(der_read_set_content<&[u8],Vec<DerObject> >,
many0!(complete!(parse_der))
);
pub fn der_read_element_content_as(i:&[u8], tag:u8, len:usize) -> IResult<&[u8], DerObjectContent> {
match tag {
0x01 => {
match be_u8(i) {
Ok((rem,0x00)) => Ok((rem,DerObjectContent::Boolean(false))),
Ok((rem,0xff)) => Ok((rem,DerObjectContent::Boolean(true))),
Ok((_,_) ) => Err(Err::Error(error_position!(i, ErrorKind::Verify))),
Err(e) => Err(e)
}
},
0x02 => {
map!(i,
take!(len),
|i| { DerObjectContent::Integer(i) }
)
},
0x03 => {
do_parse!(i,
ignored_bits: be_u8 >>
error_if!(len == 0, ErrorKind::LengthValue) >>
s: take!(len - 1) >> ( DerObjectContent::BitString(ignored_bits,BitStringObject{ data:s }) )
)
},
0x04 => {
map!(i,
take!(len), |s| { DerObjectContent::OctetString(s) }
)
},
0x05 => { Ok((i,DerObjectContent::Null)) },
0x06 => {
do_parse!(i,
error_if!(len == 0, ErrorKind::LengthValue) >>
oid: map_res!(take!(len),der_read_oid) >>
( DerObjectContent::OID(Oid::from(&oid)) )
)
},
0x0a => {
map!(i,
parse_hex_to_u64!(len),
|i| { DerObjectContent::Enum(i) }
)
},
0x0c => {
map!(i,
take!(len), |s| { DerObjectContent::UTF8String(s) }
)
},
0x10 => {
map!(i,
flat_take!(len,der_read_sequence_content),
|l| { DerObjectContent::Sequence(l) }
)
},
0x11 => {
map!(i,
flat_take!(len,der_read_set_content),
|l| { DerObjectContent::Set(l) }
)
},
0x12 => {
map!(i,
take!(len), |s| { DerObjectContent::NumericString(s) }
)
},
0x13 => {
map!(i,
take!(len), |s| { DerObjectContent::PrintableString(s) }
)
},
0x14 => {
map!(i,
take!(len), |s| { DerObjectContent::T61String(s) }
)
},
0x16 => {
map!(i,
take!(len), |s| { DerObjectContent::IA5String(s) }
)
},
0x17 => {
map!(i,
take!(len), |s| { DerObjectContent::UTCTime(s) }
)
},
0x18 => {
map!(i,
take!(len), |s| { DerObjectContent::GeneralizedTime(s) }
)
},
0x1b => {
map!(i,
take!(len), |s| { DerObjectContent::GeneralString(s) }
)
},
0x1e => {
map!(i,
take!(len), |s| { DerObjectContent::BmpString(s) }
)
},
_ => { Err(Err::Error(error_position!(i, ErrorKind::Custom(DER_TAG_UNKNOWN)))) },
}
}
pub fn der_read_element_content(i: &[u8], hdr: DerObjectHeader) -> IResult<&[u8], DerObject> {
match hdr.class {
0b00 |
0b11 => (),
0b01 |
0b10 => return map!(
i,
take!(hdr.len),
|b| { DerObject::from_header_and_content(hdr,DerObjectContent::Unknown(b)) }
),
_ => { return Err(Err::Error(error_position!(i, ErrorKind::Custom(DER_CLASS_ERROR)))); },
}
match der_read_element_content_as(i, hdr.tag, hdr.len as usize) {
Ok((rem,content)) => {
Ok((rem, DerObject::from_header_and_content(hdr,content)))
},
Err(Err::Error(Context::Code(_, ErrorKind::Custom(DER_TAG_UNKNOWN)))) => {
map!(i,
take!(hdr.len),
|b| { DerObject::from_header_and_content(hdr,DerObjectContent::Unknown(b)) }
)
}
Err(e) => Err(e)
}
}
pub fn parse_der_bool(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Boolean as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
error_if!(hdr.len != 1, ErrorKind::Custom(DER_INVALID_LENGTH)) >>
b: verify!(be_u8, |b| b==0x00 || b==0xff) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::Boolean(b != 0)) )
)
}
pub fn parse_der_integer(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Integer as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::Integer(content)) )
)
}
pub fn parse_der_bitstring(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::BitString as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
ignored_bits: be_u8 >>
error_if!(hdr.len < 1, ErrorKind::Custom(DER_INVALID_LENGTH)) >>
error_if!(hdr.is_constructed(), ErrorKind::Custom(DER_UNSUPPORTED)) >>
content: take!(hdr.len - 1) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::BitString(ignored_bits,BitStringObject{data:content})) )
)
}
pub fn parse_der_octetstring(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::OctetString as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::OctetString(content)) )
)
}
pub fn parse_der_null(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Null as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::Null) )
)
}
pub fn parse_der_oid(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Oid as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: map_res!(take!(hdr.len),der_read_oid) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::OID(Oid::from(&content))) )
)
}
pub fn parse_der_enum(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Enumerated as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: parse_hex_to_u64!(hdr.len) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::Enum(content)) )
)
}
pub fn parse_der_utf8string(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Utf8String as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::UTF8String(content)) )
)
}
pub fn parse_der_sequence(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Sequence as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: flat_take!(hdr.len as usize,der_read_sequence_content) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::Sequence(content)) )
)
}
pub fn parse_der_set(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Set as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: flat_take!(hdr.len as usize,der_read_set_content) >>
( DerObject::from_header_and_content(hdr, DerObjectContent::Set(content)) )
)
}
pub fn parse_der_numericstring(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::NumericString as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::NumericString(content)) )
)
}
pub fn parse_der_printablestring(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::PrintableString as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::PrintableString(content)) )
)
}
pub fn parse_der_ia5string(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::Ia5String as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::IA5String(content)) )
)
}
pub fn parse_der_t61string(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::T61String as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::T61String(content)) )
)
}
pub fn parse_der_bmpstring(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::BmpString as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::BmpString(content)) )
)
}
pub fn parse_der_utctime(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::UtcTime as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::UTCTime(content)) )
)
}
pub fn parse_der_generalizedtime(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::GeneralizedTime as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::GeneralizedTime(content)) )
)
}
pub fn parse_der_generalstring(i:&[u8]) -> IResult<&[u8],DerObject> {
do_parse!(
i,
hdr: der_read_element_header >>
error_if!(hdr.tag != DerTag::GeneralString as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: take!(hdr.len) >> ( DerObject::from_header_and_content(hdr, DerObjectContent::GeneralString(content)) )
)
}
pub fn parse_der_explicit_failed(i:&[u8], tag: u8) -> IResult<&[u8],DerObject,u32> {
value!(i,DerObject::from_obj(DerObjectContent::ContextSpecific(tag,None)))
}
pub fn parse_der_explicit<F>(i:&[u8], tag: u8, f:F) -> IResult<&[u8],DerObject,u32>
where F: Fn(&[u8]) -> IResult<&[u8],DerObject,u32>
{
alt_complete!(
i,
do_parse!(
hdr: der_read_element_header >>
error_if!(hdr.tag != tag as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: f >>
(
DerObject::from_header_and_content(
hdr,
DerObjectContent::ContextSpecific(tag,Some(Box::new(content)))
)
)
) |
apply!(parse_der_explicit_failed,tag)
)
}
pub fn parse_der_implicit<F>(i:&[u8], tag: u8, f:F) -> IResult<&[u8],DerObject,u32>
where F: Fn(&[u8], u8, usize) -> IResult<&[u8],DerObjectContent,u32>
{
alt_complete!(
i,
do_parse!(
hdr: der_read_element_header >>
error_if!(hdr.tag != tag as u8, ErrorKind::Custom(DER_TAG_ERROR)) >>
content: map!(
apply!(f, tag, hdr.len as usize),
|b| { DerObject::from_obj(b) }
) >>
(
DerObject::from_header_and_content(
hdr,
DerObjectContent::ContextSpecific(tag,Some(Box::new(content)))
)
)
) |
apply!(parse_der_explicit_failed,tag)
)
}
named!(pub parse_der<&[u8],DerObject>,
do_parse!(
hdr: der_read_element_header >>
error_if!(hdr.len > ::std::u32::MAX as u64, ErrorKind::Custom(DER_INVALID_LENGTH)) >>
content: apply!(der_read_element_content,hdr) >>
( content )
)
);
#[cfg(test)]
mod tests {
use der_parser::*;
use nom::{IResult,Err,ErrorKind};
#[test]
fn test_der_bool() {
let empty = &b""[..];
let b_true = DerObject::from_obj(DerObjectContent::Boolean(true));
let b_false = DerObject::from_obj(DerObjectContent::Boolean(false));
assert_eq!(parse_der_bool(&[0x01, 0x01, 0x00]), Ok((empty, b_false)));
assert_eq!(parse_der_bool(&[0x01, 0x01, 0xff]), Ok((empty, b_true)));
assert_eq!(parse_der_bool(&[0x01, 0x01, 0x7f]), Err(Err::Error(error_position!(&[0x7f][..],ErrorKind::Verify))));
}
#[test]
fn test_der_int() {
let empty = &b""[..];
let bytes = [0x02, 0x03, 0x01, 0x00, 0x01];
let expected = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01"));
assert_eq!(parse_der_integer(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_int_as_u32() {
let val = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01"));
assert_eq!(val.content.as_u32(), Ok(65537));
let val = DerObject::from_obj(DerObjectContent::Integer(b"\x01\x00\x01\x00\x01"));
assert_eq!(val.content.as_u32(), Err(DerError::IntegerTooLarge));
}
#[test]
fn test_der_int_long() {
let empty = &b""[..];
let bytes = [0x02, 0x0a, 0x39, 0x11, 0x45, 0x10, 0x94, 0x39, 0x11, 0x45, 0x10, 0x94];
let expected = DerObject::from_obj(DerObjectContent::Integer(&bytes[2..]));
assert_eq!(parse_der_integer(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_octetstring() {
let empty = &b""[..];
let bytes = [ 0x04, 0x05,
0x41, 0x41, 0x41, 0x41, 0x41,
];
let expected = DerObject::from_obj(DerObjectContent::OctetString(b"AAAAA"));
assert_eq!(parse_der_octetstring(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_null() {
let empty = &b""[..];
let expected = DerObject::from_obj(DerObjectContent::Null);
assert_eq!(parse_der_null(&[0x05, 0x00]), Ok((empty, expected)));
}
#[test]
fn test_der_oid() {
let empty = &b""[..];
let bytes = [0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05];
let expected = DerObject::from_obj(DerObjectContent::OID(Oid::from(&[1, 2, 840, 113549, 1, 1, 5])));
assert_eq!(parse_der_oid(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_enum() {
let empty = &b""[..];
let expected = DerObject::from_obj(DerObjectContent::Enum(2));
assert_eq!(parse_der_enum(&[0x0a, 0x01, 0x02]), Ok((empty, expected)));
}
#[test]
fn test_der_utf8string() {
let empty = &b""[..];
let bytes = [ 0x0c, 0x0a,
0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65
];
let expected = DerObject::from_obj(DerObjectContent::UTF8String(b"Some-State"));
assert_eq!(parse_der_utf8string(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_seq() {
let empty = &b""[..];
let bytes = [ 0x30, 0x05,
0x02, 0x03, 0x01, 0x00, 0x01,
];
let expected = DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
]));
assert_eq!(parse_der_sequence(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_set() {
let empty = &b""[..];
let bytes = [
0x31, 0x05,
0x02, 0x03, 0x01, 0x00, 0x01, ];
let expected = DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
]));
assert_eq!(parse_der(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_set_defined() {
let empty = &b""[..];
let bytes = [ 0x31, 0x0a,
0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x00,
];
let expected = DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
DerObject::from_int_slice(b"\x01\x00\x00"),
]));
fn parser(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_set_defined!(i,
parse_der_integer,
parse_der_integer
)
};
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_seq_defined() {
let empty = &b""[..];
let bytes = [ 0x30, 0x0a,
0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x00,
];
let expected = DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
DerObject::from_int_slice(b"\x01\x00\x00"),
]));
fn parser(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_defined!(i,
parse_der_integer,
parse_der_integer
)
};
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_seq_of() {
let empty = &b""[..];
let bytes = [ 0x30, 0x0a,
0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x00,
];
let expected = DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
DerObject::from_int_slice(b"\x01\x00\x00"),
]));
fn parser(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_of!(i, parse_der_integer)
};
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_seq_of_incomplete() {
let bytes = [ 0x30, 0x07,
0x02, 0x03, 0x01, 0x00, 0x01,
0x00, 0x00,
];
fn parser(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_of!(i, parse_der_integer)
};
assert_eq!(parser(&bytes), Err(Err::Error(error_position!(&bytes[7..], ErrorKind::Eof))));
}
#[test]
fn test_der_set_of() {
let empty = &b""[..];
let bytes = [ 0x31, 0x0a,
0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x00,
];
let expected = DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
DerObject::from_int_slice(b"\x01\x00\x00"),
]));
fn parser(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_set_of!(i, parse_der_integer)
};
assert_eq!(parser(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_utctime() {
let empty = &b""[..];
let bytes = [0x17, 0x0D, 0x30, 0x32, 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x32, 0x39, 0x32, 0x33, 0x5A ];
let expected = DerObject{
class: 0,
structured: 0,
tag: DerTag::UtcTime as u8,
content: DerObjectContent::UTCTime(&bytes[2..]),
};
assert_eq!(parse_der(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_generalizedtime() {
let empty = &b""[..];
let bytes = [0x18, 0x0D, 0x30, 0x32, 0x31, 0x32, 0x31, 0x33, 0x31, 0x34, 0x32, 0x39, 0x32, 0x33, 0x5A ];
let expected = DerObject{
class: 0,
structured: 0,
tag: DerTag::GeneralizedTime as u8,
content: DerObjectContent::GeneralizedTime(&bytes[2..]),
};
assert_eq!(parse_der_generalizedtime(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_generalstring() {
let empty = &b""[..];
let bytes = [ 0x1b, 0x04,
0x63, 0x69, 0x66, 0x73
];
let expected = DerObject::from_obj(DerObjectContent::GeneralString(b"cifs"));
assert_eq!(parse_der_generalstring(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_contextspecific() {
let bytes = [0xa0, 0x03, 0x02, 0x01, 0x02];
let empty = &b""[..];
let expected = DerObject{
class: 2,
structured: 1,
tag: 0,
content: DerObjectContent::Unknown(&bytes[2..]),
};
assert_eq!(parse_der(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_explicit() {
let empty = &b""[..];
let bytes = [0xa0, 0x03, 0x02, 0x01, 0x02];
let expected = DerObject{
class: 2,
structured: 1,
tag: 0,
content: DerObjectContent::ContextSpecific(0,Some(Box::new(DerObject::from_int_slice(b"\x02")))),
};
assert_eq!(parse_der_explicit(&bytes, 0, parse_der_integer), Ok((empty, expected)));
let expected2 = DerObject::from_obj(DerObjectContent::ContextSpecific(1,None));
assert_eq!(parse_der_explicit(&bytes, 1, parse_der_integer), Ok((&bytes[..], expected2)));
}
#[test]
fn test_der_implicit() {
let empty = &b""[..];
let bytes = [0x81, 0x04, 0x70, 0x61, 0x73, 0x73];
let pass = DerObject::from_obj(DerObjectContent::IA5String(b"pass"));
let expected = DerObject{
class: 2,
structured: 0,
tag: 1,
content: DerObjectContent::ContextSpecific(1,Some(Box::new(pass))),
};
fn der_read_ia5string_content(i:&[u8], _tag:u8, len: usize) -> IResult<&[u8],DerObjectContent,u32> {
der_read_element_content_as(i, DerTag::Ia5String as u8, len)
}
assert_eq!(parse_der_implicit(&bytes, 1, der_read_ia5string_content), Ok((empty, expected)));
let expected2 = DerObject::from_obj(DerObjectContent::ContextSpecific(2,None));
assert_eq!(parse_der_implicit(&bytes, 2, der_read_ia5string_content), Ok((&bytes[..], expected2)));
}
#[test]
fn test_der_optional() {
let empty = &b""[..];
let bytes1 = [ 0x30, 0x0a,
0x0a, 0x03, 0x00, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x01,
];
let bytes2 = [ 0x30, 0x05,
0x02, 0x03, 0x01, 0x00, 0x01,
];
let expected1 = DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(
DerObjectContent::ContextSpecific(0, Some(Box::new(DerObject::from_obj(DerObjectContent::Enum(1)))))
),
DerObject::from_int_slice(b"\x01\x00\x01"),
]));
let expected2 = DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(
DerObjectContent::ContextSpecific(0, None),
),
DerObject::from_int_slice(b"\x01\x00\x01"),
]));
fn parse_optional_enum(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_optional!(i, parse_der_enum)
}
fn parser(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_defined!(i,
parse_optional_enum,
parse_der_integer
)
};
assert_eq!(parser(&bytes1), Ok((empty, expected1)));
assert_eq!(parser(&bytes2), Ok((empty, expected2)));
}
#[test]
fn test_der_seq_dn() {
let empty = &b""[..];
let bytes = [
0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x46, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64
];
let expected = DerObject::from_obj(
DerObjectContent::Sequence(
vec![
DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(DerObjectContent::OID(Oid::from(&[2, 5, 4, 6]))), DerObject::from_obj(DerObjectContent::PrintableString(b"FR")),
])),
])),
DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(DerObjectContent::OID(Oid::from(&[2, 5, 4, 8]))), DerObject::from_obj(DerObjectContent::UTF8String(b"Some-State")),
])),
])),
DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(DerObjectContent::OID(Oid::from(&[2, 5, 4, 10]))), DerObject::from_obj(DerObjectContent::UTF8String(b"Internet Widgits Pty Ltd")),
])),
])),
]
)
);
assert_eq!(parse_der(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_seq_dn_defined() {
let empty = &b""[..];
let bytes = [
0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x46, 0x52, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65,
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67,
0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64
];
let expected = DerObject::from_obj(
DerObjectContent::Sequence(
vec![
DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(DerObjectContent::OID(Oid::from(&[2, 5, 4, 6]))), DerObject::from_obj(DerObjectContent::PrintableString(b"FR")),
])),
])),
DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(DerObjectContent::OID(Oid::from(&[2, 5, 4, 8]))), DerObject::from_obj(DerObjectContent::UTF8String(b"Some-State")),
])),
])),
DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_obj(DerObjectContent::OID(Oid::from(&[2, 5, 4, 10]))), DerObject::from_obj(DerObjectContent::UTF8String(b"Internet Widgits Pty Ltd")),
])),
])),
]
)
);
#[inline]
fn parse_directory_string(i:&[u8]) -> IResult<&[u8],DerObject> {
alt!(i, parse_der_utf8string | parse_der_printablestring | parse_der_ia5string)
}
#[inline]
fn parse_attr_type_and_value(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_defined!(i,
parse_der_oid,
parse_directory_string
)
};
#[inline]
fn parse_rdn(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_set_defined!(i, parse_attr_type_and_value)
}
#[inline]
fn parse_name(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_defined!(i,
parse_rdn,
parse_rdn,
parse_rdn
)
}
assert_eq!(parse_name(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_defined_seq_macros() {
fn localparse_seq(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_sequence_defined_m!(i,
parse_der_integer >>
call!(parse_der_integer)
)
}
let empty = &b""[..];
let bytes = [ 0x30, 0x0a,
0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x00,
];
let expected = DerObject::from_obj(DerObjectContent::Sequence(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
DerObject::from_int_slice(b"\x01\x00\x00"),
]));
assert_eq!(localparse_seq(&bytes), Ok((empty, expected)));
}
#[test]
fn test_der_defined_set_macros() {
fn localparse_set(i:&[u8]) -> IResult<&[u8],DerObject> {
parse_der_set_defined_m!(i,
parse_der_integer >>
call!(parse_der_integer)
)
}
let empty = &b""[..];
let bytes = [ 0x31, 0x0a,
0x02, 0x03, 0x01, 0x00, 0x01,
0x02, 0x03, 0x01, 0x00, 0x00,
];
let expected = DerObject::from_obj(DerObjectContent::Set(vec![
DerObject::from_int_slice(b"\x01\x00\x01"),
DerObject::from_int_slice(b"\x01\x00\x00"),
]));
assert_eq!(localparse_set(&bytes), Ok((empty, expected)));
}
#[test]
fn test_parse_u32() {
let empty = &b""[..];
assert_eq!(parse_der_u32(&[0x02, 0x01, 0x01]),Ok((empty,1)));
assert_eq!(parse_der_u32(&[0x02, 0x01, 0xff]),Ok((empty,255)));
assert_eq!(parse_der_u32(&[0x02, 0x02, 0x01, 0x23]),Ok((empty,0x123)));
assert_eq!(parse_der_u32(&[0x02, 0x02, 0xff, 0xff]),Ok((empty,0xffff)));
assert_eq!(parse_der_u32(&[0x02, 0x03, 0x01, 0x23, 0x45]),Ok((empty,0x12345)));
assert_eq!(parse_der_u32(&[0x02, 0x03, 0xff, 0xff, 0xff]),Ok((empty,0xffffff)));
assert_eq!(parse_der_u32(&[0x02, 0x04, 0x01, 0x23, 0x45, 0x67]),Ok((empty,0x1234567)));
assert_eq!(parse_der_u32(&[0x02, 0x04, 0xff, 0xff, 0xff, 0xff]),Ok((empty,0xffffffff)));
let s = &[0x02, 0x05, 0x01, 0x23, 0x45, 0x67, 0x89];
assert_eq!(parse_der_u32(s),Err(Err::Error(error_position!(&s[2..],ErrorKind::Custom(DER_INTEGER_TOO_LARGE)))));
let s = &[0x01, 0x01, 0xff];
assert_eq!(parse_der_u32(s),Err(Err::Error(error_position!(&s[2..], ErrorKind::Custom(DER_TAG_ERROR)))));
}
#[test]
fn test_parse_u64() {
let empty = &b""[..];
assert_eq!(parse_der_u64(&[0x02, 0x01, 0x01]),Ok((empty,1)));
assert_eq!(parse_der_u64(&[0x02, 0x01, 0xff]),Ok((empty,255)));
assert_eq!(parse_der_u64(&[0x02, 0x02, 0x01, 0x23]),Ok((empty,0x123)));
assert_eq!(parse_der_u64(&[0x02, 0x02, 0xff, 0xff]),Ok((empty,0xffff)));
assert_eq!(parse_der_u64(&[0x02, 0x03, 0x01, 0x23, 0x45]),Ok((empty,0x12345)));
assert_eq!(parse_der_u64(&[0x02, 0x03, 0xff, 0xff, 0xff]),Ok((empty,0xffffff)));
assert_eq!(parse_der_u64(&[0x02, 0x04, 0x01, 0x23, 0x45, 0x67]),Ok((empty,0x1234567)));
assert_eq!(parse_der_u64(&[0x02, 0x04, 0xff, 0xff, 0xff, 0xff]),Ok((empty,0xffffffff)));
assert_eq!(parse_der_u64(&[0x02, 0x05, 0x01, 0x23, 0x45, 0x67, 0x89]),Ok((empty,0x123456789)));
let s = &[0x01, 0x01, 0xff];
assert_eq!(parse_der_u64(s),Err(Err::Error(error_position!(&s[2..], ErrorKind::Custom(DER_TAG_ERROR)))));
}
}