Add Display and Error implementations for ASN1DecodeError, plus some context.

This commit is contained in:
2018-10-26 12:04:31 -07:00
parent bdb8f7f8aa
commit 823fc31f6f

View File

@@ -40,6 +40,7 @@ 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;
use std::str::Utf8Error;
/// An ASN.1 block class. /// An ASN.1 block class.
/// ///
@@ -245,13 +246,59 @@ const PRINTABLE_CHARS: &'static str =
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
pub enum ASN1DecodeErr { pub enum ASN1DecodeErr {
EmptyBuffer, EmptyBuffer,
BadBooleanLength, BadBooleanLength(usize),
LengthTooLarge, LengthTooLarge(usize),
UTF8DecodeFailure, UTF8DecodeFailure(Utf8Error),
PrintableStringDecodeFailure, PrintableStringDecodeFailure,
InvalidDateValue(String) InvalidDateValue(String)
} }
impl fmt::Display for ASN1DecodeErr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ASN1DecodeErr::EmptyBuffer =>
write!(f, "Encountered an empty buffer decoding ASN1 block."),
ASN1DecodeErr::BadBooleanLength(x) =>
write!(f, "Bad length field in boolean block: {}", x),
ASN1DecodeErr::LengthTooLarge(x) =>
write!(f, "Length field too large for object type: {}", x),
ASN1DecodeErr::UTF8DecodeFailure(x) =>
write!(f, "UTF8 string failed to properly decode: {}", x),
ASN1DecodeErr::PrintableStringDecodeFailure =>
write!(f, "Printable string failed to properly decode."),
ASN1DecodeErr::InvalidDateValue(x) =>
write!(f, "Invalid date value: {}", x)
}
}
}
impl Error for ASN1DecodeErr {
fn description(&self) -> &str {
match self {
ASN1DecodeErr::EmptyBuffer =>
"Encountered an empty buffer decoding ASN1 block.",
ASN1DecodeErr::BadBooleanLength(_) =>
"Bad length field in boolean block.",
ASN1DecodeErr::LengthTooLarge(_) =>
"Length field too large for object type.",
ASN1DecodeErr::UTF8DecodeFailure(_) =>
"UTF8 string failed to properly decode.",
ASN1DecodeErr::PrintableStringDecodeFailure =>
"Printable string failed to properly decode.",
ASN1DecodeErr::InvalidDateValue(_) =>
"Invalid date value."
}
}
fn cause(&self) -> Option<&Error> {
None
}
fn source(&self) -> Option<&(Error + 'static)> {
None
}
}
/// An error that can arise encoding ASN.1 primitive blocks. /// An error that can arise encoding ASN.1 primitive blocks.
#[derive(Clone,Debug,PartialEq)] #[derive(Clone,Debug,PartialEq)]
pub enum ASN1EncodeErr { pub enum ASN1EncodeErr {
@@ -310,7 +357,7 @@ fn from_der_(i: &[u8], start_offset: usize)
// BOOLEAN // BOOLEAN
Some(0x01) => { Some(0x01) => {
if len != 1 { if len != 1 {
return Err(ASN1DecodeErr::BadBooleanLength); return Err(ASN1DecodeErr::BadBooleanLength(len));
} }
result.push(ASN1Block::Boolean(class, soff, body[0] != 0)); result.push(ASN1Block::Boolean(class, soff, body[0] != 0));
} }
@@ -367,8 +414,8 @@ fn from_der_(i: &[u8], start_offset: usize)
match String::from_utf8(body.to_vec()) { match String::from_utf8(body.to_vec()) {
Ok(v) => Ok(v) =>
result.push(ASN1Block::UTF8String(class, soff, v)), result.push(ASN1Block::UTF8String(class, soff, v)),
Err(_) => Err(e) =>
return Err(ASN1DecodeErr::UTF8DecodeFailure) return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error()))
} }
} }
// SEQUENCE // SEQUENCE
@@ -408,8 +455,8 @@ fn from_der_(i: &[u8], start_offset: usize)
match String::from_utf8(body.to_vec()) { match String::from_utf8(body.to_vec()) {
Ok(v) => Ok(v) =>
result.push(ASN1Block::TeletexString(class, soff, v)), result.push(ASN1Block::TeletexString(class, soff, v)),
Err(_) => Err(e) =>
return Err(ASN1DecodeErr::UTF8DecodeFailure) return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error()))
} }
} }
// IA5 (ASCII) STRING // IA5 (ASCII) STRING
@@ -461,8 +508,8 @@ fn from_der_(i: &[u8], start_offset: usize)
match String::from_utf8(body.to_vec()) { match String::from_utf8(body.to_vec()) {
Ok(v) => Ok(v) =>
result.push(ASN1Block::UniversalString(class, soff, v)), result.push(ASN1Block::UniversalString(class, soff, v)),
Err(_) => Err(e) =>
return Err(ASN1DecodeErr::UTF8DecodeFailure) return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error()))
} }
} }
// UNIVERSAL STRINGS // UNIVERSAL STRINGS
@@ -470,8 +517,8 @@ fn from_der_(i: &[u8], start_offset: usize)
match String::from_utf8(body.to_vec()) { match String::from_utf8(body.to_vec()) {
Ok(v) => Ok(v) =>
result.push(ASN1Block::BMPString(class, soff, v)), result.push(ASN1Block::BMPString(class, soff, v)),
Err(_) => Err(e) =>
return Err(ASN1DecodeErr::UTF8DecodeFailure) return Err(ASN1DecodeErr::UTF8DecodeFailure(e.utf8_error()))
} }
} }
// Dunno. // Dunno.
@@ -540,7 +587,7 @@ fn decode_length(i: &[u8], index: &mut usize) -> Result<usize,ASN1DecodeErr> {
let mut res = 0; let mut res = 0;
if lenlen > size_of::<usize>() { if lenlen > size_of::<usize>() {
return Err(ASN1DecodeErr::LengthTooLarge); return Err(ASN1DecodeErr::LengthTooLarge(lenlen));
} }
while lenlen > 0 { while lenlen > 0 {