use noxtls_core::{Error, Result};
#[derive(Debug, Clone)]
pub struct DerNode<'a> {
pub tag: u8,
pub body: &'a [u8],
}
pub fn parse_der_node(input: &[u8]) -> Result<(DerNode<'_>, &[u8])> {
if input.len() < 2 {
return Err(Error::ParseFailure("DER node too short"));
}
let tag = input[0];
let (len, len_len) = parse_der_length(&input[1..])?;
let start = 1_usize
.checked_add(len_len)
.ok_or(Error::ParseFailure("DER length arithmetic overflow"))?;
let end = start
.checked_add(len)
.ok_or(Error::ParseFailure("DER length arithmetic overflow"))?;
if input.len() < end {
return Err(Error::ParseFailure("DER length exceeds input"));
}
Ok((
DerNode {
tag,
body: &input[start..end],
},
&input[end..],
))
}
pub fn parse_der_length(input: &[u8]) -> Result<(usize, usize)> {
if input.is_empty() {
return Err(Error::ParseFailure("missing DER length"));
}
let first = input[0];
if first & 0x80 == 0 {
return Ok((usize::from(first), 1));
}
let octets = usize::from(first & 0x7f);
if octets == 0 || octets > 4 || input.len() < 1 + octets {
return Err(Error::ParseFailure("unsupported DER length"));
}
if input[1] == 0 {
return Err(Error::ParseFailure("non-canonical DER length"));
}
if octets == 1 && input[1] < 0x80 {
return Err(Error::ParseFailure("non-canonical DER length"));
}
let mut len = 0_usize;
for b in &input[1..1 + octets] {
len = (len << 8) | usize::from(*b);
}
Ok((len, 1 + octets))
}