use crate::error::{Lib3mfError, Result};
use crate::model::crypto::*;
use crate::parser::xml_parser::{XmlParser, get_attribute};
use quick_xml::events::Event;
use std::io::BufRead;
pub fn parse_signature<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Signature> {
let mut signature = Signature::default();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
Event::End(e) if e.local_name().as_ref() == b"Signature" => return Ok(signature),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in Signature".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name)) = evt_info {
match local_name.as_slice() {
b"SignedInfo" => {
signature.signed_info = parse_signed_info(parser)?;
}
b"SignatureValue" => {
let val = parser.read_text_content()?;
signature.signature_value = SignatureValue { value: val };
}
b"KeyInfo" => {
signature.key_info = Some(parse_key_info(parser)?);
}
_ => {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
fn parse_signed_info<R: BufRead>(parser: &mut XmlParser<R>) -> Result<SignedInfo> {
let mut info = SignedInfo::default();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => {
let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
let uri = get_attribute(&e, b"URI").map(|s| s.into_owned());
Some((
e.local_name().as_ref().to_vec(),
e.name().as_ref().to_vec(),
alg,
uri,
false,
))
}
Event::Empty(e) => {
let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
let uri = get_attribute(&e, b"URI").map(|s| s.into_owned());
Some((
e.local_name().as_ref().to_vec(),
e.name().as_ref().to_vec(),
alg,
uri,
true,
))
}
Event::End(e) if e.local_name().as_ref() == b"SignedInfo" => return Ok(info),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in SignedInfo".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name, alg, uri, is_empty)) = evt_info {
match local_name.as_slice() {
b"CanonicalizationMethod" => {
info.canonicalization_method = CanonicalizationMethod {
algorithm: alg.unwrap_or_default(),
};
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
b"SignatureMethod" => {
info.signature_method = SignatureMethod {
algorithm: alg.unwrap_or_default(),
};
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
b"Reference" => {
if !is_empty {
let r = parse_reference_content(parser, uri.unwrap_or_default())?;
info.references.push(r);
} else {
let r = Reference {
uri: uri.unwrap_or_default(),
..Default::default()
};
info.references.push(r);
}
}
_ => {
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
}
fn parse_reference_content<R: BufRead>(
parser: &mut XmlParser<R>,
uri: String,
) -> Result<Reference> {
let mut r = Reference {
uri,
..Default::default()
};
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => {
let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
Some((
e.local_name().as_ref().to_vec(),
e.name().as_ref().to_vec(),
alg,
false,
))
}
Event::Empty(e) => {
let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
Some((
e.local_name().as_ref().to_vec(),
e.name().as_ref().to_vec(),
alg,
true,
))
}
Event::End(e) if e.local_name().as_ref() == b"Reference" => return Ok(r),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in Reference".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name, alg, is_empty)) = evt_info {
match local_name.as_slice() {
b"DigestMethod" => {
r.digest_method = DigestMethod {
algorithm: alg.unwrap_or_default(),
};
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
b"DigestValue" => {
if !is_empty {
let val = parser.read_text_content()?;
r.digest_value = DigestValue { value: val };
}
}
b"Transforms" => {
if !is_empty {
let transforms = parse_transforms_content(parser)?;
r.transforms = Some(transforms);
}
}
_ => {
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
}
fn parse_transforms_content<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<Transform>> {
let mut transforms = Vec::new();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => {
let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
Some((
e.local_name().as_ref().to_vec(),
e.name().as_ref().to_vec(),
alg,
false,
))
}
Event::Empty(e) => {
let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
Some((
e.local_name().as_ref().to_vec(),
e.name().as_ref().to_vec(),
alg,
true,
))
}
Event::End(e) if e.local_name().as_ref() == b"Transforms" => return Ok(transforms),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in Transforms".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name, alg, is_empty)) = evt_info {
match local_name.as_slice() {
b"Transform" => {
transforms.push(Transform {
algorithm: alg.unwrap_or_default(),
});
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
_ => {
if !is_empty {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
}
fn parse_key_info<R: BufRead>(parser: &mut XmlParser<R>) -> Result<KeyInfo> {
let mut info = KeyInfo::default();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
Event::End(e) if e.local_name().as_ref() == b"KeyInfo" => return Ok(info),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in KeyInfo".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name)) = evt_info {
match local_name.as_slice() {
b"KeyName" => {
let val = parser.read_text_content()?;
info.key_name = Some(val);
}
b"KeyValue" => {
info.key_value = Some(parse_key_value(parser)?);
}
b"X509Data" => {
info.x509_data = Some(parse_x509_data(parser)?);
}
_ => {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
fn parse_x509_data<R: BufRead>(parser: &mut XmlParser<R>) -> Result<X509Data> {
let mut data = X509Data::default();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
Event::End(e) if e.local_name().as_ref() == b"X509Data" => return Ok(data),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in X509Data".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name)) = evt_info {
match local_name.as_slice() {
b"X509Certificate" => {
let val = parser.read_text_content()?;
let cleaned = val.chars().filter(|c| !c.is_whitespace()).collect();
data.certificate = Some(cleaned);
}
_ => {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
fn parse_key_value<R: BufRead>(parser: &mut XmlParser<R>) -> Result<KeyValue> {
let mut val = KeyValue::default();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
Event::End(e) if e.local_name().as_ref() == b"KeyValue" => return Ok(val),
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in KeyValue".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name)) = evt_info {
match local_name.as_slice() {
b"RSAKeyValue" => {
val.rsa_key_value = Some(parse_rsa_key_value(parser)?);
}
_ => {
parser.read_to_end(&raw_name)?;
}
}
}
}
}
fn parse_rsa_key_value<R: BufRead>(parser: &mut XmlParser<R>) -> Result<RSAKeyValue> {
let mut modulus = String::new();
let mut exponent = String::new();
loop {
let evt_info = match parser.read_next_event()? {
Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
Event::End(e) if e.local_name().as_ref() == b"RSAKeyValue" => {
return Ok(RSAKeyValue { modulus, exponent });
}
Event::Eof => {
return Err(Lib3mfError::Validation(
"Unexpected EOF in RSAKeyValue".to_string(),
));
}
_ => None,
};
if let Some((local_name, raw_name)) = evt_info {
match local_name.as_slice() {
b"Modulus" => modulus = parser.read_text_content()?,
b"Exponent" => exponent = parser.read_text_content()?,
_ => {
parser.read_to_end(&raw_name)?;
}
}
}
}
}