use crate::base::der::{Element, next_element, read_element};
use crate::{Error, Result};
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct MtcCaParameters {
pub signature_algorithm_oid: String,
pub min_serial: u64,
pub max_serial: u64,
pub min_serial_content: Vec<u8>,
pub max_serial_content: Vec<u8>,
}
pub(crate) fn uint64_content(content: &[u8]) -> Result<u64> {
if content.is_empty() {
return Err(Error::Malformed("INTEGER"));
}
let padded = content.first() == Some(&0) && content.get(1).is_some_and(|b| b & 0x80 != 0);
let bytes = if padded { &content[1..] } else { content };
if bytes.len() > 8 || bytes[0] & 0x80 != 0 || (bytes.len() > 1 && bytes[0] == 0) {
return Err(Error::Malformed("INTEGER"));
}
Ok(bytes.iter().fold(0u64, |v, &b| v << 8 | u64::from(b)))
}
pub fn parse_mtc_ca_parameters(bytes: &[u8]) -> Result<MtcCaParameters> {
let (sequence, rest) = read_element(bytes).ok_or(Error::Malformed("MTCCA extension"))?;
if sequence.tag != 0x30 || !rest.is_empty() {
return Err(Error::Malformed("MTCCA extension"));
}
let mut input = sequence.content;
let algorithm = next_element(&mut input, "MTCCA sigAlg")?;
if algorithm.tag != 0x30 {
return Err(Error::Malformed("MTCCA sigAlg"));
}
let (oid, _) = read_element(algorithm.content).ok_or(Error::Malformed("MTCCA sigAlg OID"))?;
if oid.tag != 0x06 {
return Err(Error::Malformed("MTCCA sigAlg OID"));
}
let signature_algorithm_oid = crate::base::id::oid_content_to_dotted(oid.content)?;
let min = next_element(&mut input, "MTCCA minSerial")?;
let max = next_element(&mut input, "MTCCA maxSerial")?;
if !input.is_empty() {
return Err(Error::Malformed("MTCCA extension"));
}
let integer = |element: Element<'_>| -> Result<u64> {
if element.tag != 0x02 {
return Err(Error::Malformed("MTCCA serial"));
}
uint64_content(element.content)
};
Ok(MtcCaParameters {
signature_algorithm_oid,
min_serial: integer(min)?,
max_serial: integer(max)?,
min_serial_content: min.content.to_vec(),
max_serial_content: max.content.to_vec(),
})
}