mirror of https://github.com/briansmith/webpki
Add ASN.1 DER parsing framework.
This commit is contained in:
parent
62a20c6df2
commit
6b60cbd719
|
@ -0,0 +1,89 @@
|
|||
// Copyright 2015 Brian Smith.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
||||
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
use super::Error;
|
||||
use super::input::*;
|
||||
|
||||
const CONSTRUCTED : u8 = 1 << 5;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum Tag {
|
||||
Boolean = 0x01,
|
||||
Integer = 0x02,
|
||||
BitString = 0x03,
|
||||
OctetString = 0x04,
|
||||
Null = 0x05,
|
||||
OID = 0x06,
|
||||
Sequence = CONSTRUCTED | 0x10, // 0x30
|
||||
UTCTime = 0x17,
|
||||
GeneralizedTime = 0x18,
|
||||
}
|
||||
|
||||
pub fn expect_tag_and_get_input<'a>(input: &mut Reader<'a>, tag: Tag)
|
||||
-> Result<Input<'a>, Error> {
|
||||
let (actual_tag, inner) = try!(read_tag_and_get_input(input));
|
||||
if (tag as usize) != (actual_tag as usize) {
|
||||
return Err(Error::BadDER);
|
||||
}
|
||||
Ok(inner)
|
||||
}
|
||||
|
||||
fn read_tag_and_get_input<'a>(input: &mut Reader<'a>)
|
||||
-> Result<(u8, Input<'a>), Error> {
|
||||
let tag = try!(input.read_byte().ok_or(Error::BadDER));
|
||||
if (tag & 0x1F) == 0x1F {
|
||||
return Err(Error::BadDER) // High tag number form is not allowed.
|
||||
}
|
||||
|
||||
// If the high order bit of the first byte is set to zero then the length
|
||||
// is encoded in the seven remaining bits of that byte. Otherwise, those
|
||||
// seven bits represent the number of bytes used to encode the length.
|
||||
let length = match try!(input.read_byte().ok_or(Error::BadDER)) {
|
||||
n if (n & 0x80) == 0 => n as usize,
|
||||
0x81 => {
|
||||
let second_byte = try!(input.read_byte().ok_or(Error::BadDER));
|
||||
if second_byte < 128 {
|
||||
return Err(Error::BadDER) // Not the canonical encoding.
|
||||
}
|
||||
second_byte as usize
|
||||
},
|
||||
0x82 => {
|
||||
let second_byte = try!(input.read_byte().ok_or(Error::BadDER))
|
||||
as usize;
|
||||
let third_byte = try!(input.read_byte().ok_or(Error::BadDER))
|
||||
as usize;
|
||||
let combined = (second_byte << 8) | third_byte;
|
||||
if combined < 256 {
|
||||
return Err(Error::BadDER); // Not the canonical encoding.
|
||||
}
|
||||
combined
|
||||
},
|
||||
_ => {
|
||||
return Err(Error::BadDER); // We don't support longer lengths.
|
||||
}
|
||||
};
|
||||
|
||||
let inner = try!(input.skip_and_get_input(length).ok_or(Error::BadDER));
|
||||
Ok((tag, inner))
|
||||
}
|
||||
|
||||
// TODO: investigate taking decoder as a reference to reduce generated code
|
||||
// size.
|
||||
pub fn nested<'a, F, R>(input: &mut Reader<'a>, tag: Tag, decoder: F)
|
||||
-> Result<R, Error>
|
||||
where F : FnOnce(&mut Reader<'a>) -> Result<R, Error> {
|
||||
let inner = try!(expect_tag_and_get_input(input, tag));
|
||||
read_all(inner, Error::BadDER, decoder)
|
||||
}
|
13
src/input.rs
13
src/input.rs
|
@ -90,4 +90,17 @@ impl<'a> Reader<'a> {
|
|||
None => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn skip_and_get_input(&mut self, num_bytes: usize)
|
||||
-> Option<Input<'a>> {
|
||||
match self.i.checked_add(num_bytes) {
|
||||
Some(new_i) if new_i <= self.input.bytes.len() => {
|
||||
let ret =
|
||||
Some(Input { bytes: &self.input.bytes[self.i..new_i] });
|
||||
self.i = new_i;
|
||||
ret
|
||||
},
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,4 +12,10 @@
|
|||
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
mod der;
|
||||
mod input;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Error {
|
||||
BadDER,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue