lib3mf_core/parser/
crypto_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::crypto::*;
3use crate::parser::xml_parser::{XmlParser, get_attribute};
4use quick_xml::events::Event;
5use std::io::BufRead;
6
7pub fn parse_signature<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Signature> {
8    let mut signature = Signature::default();
9
10    loop {
11        // Read event separately to limit scope of borrow
12        let evt_info = match parser.read_next_event()? {
13            Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
14            Event::End(e) if e.local_name().as_ref() == b"Signature" => return Ok(signature),
15            Event::Eof => {
16                return Err(Lib3mfError::Validation(
17                    "Unexpected EOF in Signature".to_string(),
18                ));
19            }
20            _ => None,
21        };
22
23        if let Some((local_name, raw_name)) = evt_info {
24            match local_name.as_slice() {
25                b"SignedInfo" => {
26                    signature.signed_info = parse_signed_info(parser)?;
27                }
28                b"SignatureValue" => {
29                    let val = parser.read_text_content()?;
30                    signature.signature_value = SignatureValue { value: val };
31                }
32                b"KeyInfo" => {
33                    signature.key_info = Some(parse_key_info(parser)?);
34                }
35                _ => {
36                    parser.read_to_end(&raw_name)?;
37                }
38            }
39        }
40    }
41}
42
43fn parse_signed_info<R: BufRead>(parser: &mut XmlParser<R>) -> Result<SignedInfo> {
44    let mut info = SignedInfo::default();
45
46    loop {
47        let evt_info = match parser.read_next_event()? {
48            Event::Start(e) => {
49                let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
50                let uri = get_attribute(&e, b"URI").map(|s| s.into_owned());
51                Some((
52                    e.local_name().as_ref().to_vec(),
53                    e.name().as_ref().to_vec(),
54                    alg,
55                    uri,
56                    false,
57                ))
58            }
59            Event::Empty(e) => {
60                let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
61                let uri = get_attribute(&e, b"URI").map(|s| s.into_owned());
62                Some((
63                    e.local_name().as_ref().to_vec(),
64                    e.name().as_ref().to_vec(),
65                    alg,
66                    uri,
67                    true,
68                ))
69            }
70            Event::End(e) if e.local_name().as_ref() == b"SignedInfo" => return Ok(info),
71            Event::Eof => {
72                return Err(Lib3mfError::Validation(
73                    "Unexpected EOF in SignedInfo".to_string(),
74                ));
75            }
76            _ => None,
77        };
78
79        if let Some((local_name, raw_name, alg, uri, is_empty)) = evt_info {
80            match local_name.as_slice() {
81                b"CanonicalizationMethod" => {
82                    info.canonicalization_method = CanonicalizationMethod {
83                        algorithm: alg.unwrap_or_default(),
84                    };
85                    if !is_empty {
86                        parser.read_to_end(&raw_name)?;
87                    }
88                }
89                b"SignatureMethod" => {
90                    info.signature_method = SignatureMethod {
91                        algorithm: alg.unwrap_or_default(),
92                    };
93                    if !is_empty {
94                        parser.read_to_end(&raw_name)?;
95                    }
96                }
97                b"Reference" => {
98                    // Logic for Reference: if empty, it's invalid usually, but we handle it.
99                    // If Start, we need to recurse.
100                    if !is_empty {
101                        // We need to pass the URI we extracted.
102                        // parse_reference logic assumes it gets parser.
103                        // But parse_reference usually expects to handle Start event attributes...
104                        // Since we consumed the Start event, we must handle attributes here or pass them.
105                        // I will modify parse_reference to take URI and assume start event consumed.
106                        let r = parse_reference_content(parser, uri.unwrap_or_default())?;
107                        info.references.push(r);
108                    } else {
109                        // Empty Reference? Not really valid but...
110                        let r = Reference {
111                            uri: uri.unwrap_or_default(),
112                            ..Default::default()
113                        };
114                        info.references.push(r);
115                    }
116                }
117                _ => {
118                    if !is_empty {
119                        parser.read_to_end(&raw_name)?;
120                    }
121                }
122            }
123        }
124    }
125}
126
127// Renamed from parse_reference to parse_reference_content as it assumes Start event consumed
128fn parse_reference_content<R: BufRead>(
129    parser: &mut XmlParser<R>,
130    uri: String,
131) -> Result<Reference> {
132    let mut r = Reference {
133        uri,
134        ..Default::default()
135    };
136
137    loop {
138        let evt_info = match parser.read_next_event()? {
139            Event::Start(e) => {
140                let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
141                Some((
142                    e.local_name().as_ref().to_vec(),
143                    e.name().as_ref().to_vec(),
144                    alg,
145                    false,
146                ))
147            }
148            Event::Empty(e) => {
149                let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
150                Some((
151                    e.local_name().as_ref().to_vec(),
152                    e.name().as_ref().to_vec(),
153                    alg,
154                    true,
155                ))
156            }
157            Event::End(e) if e.local_name().as_ref() == b"Reference" => return Ok(r),
158            Event::Eof => {
159                return Err(Lib3mfError::Validation(
160                    "Unexpected EOF in Reference".to_string(),
161                ));
162            }
163            _ => None,
164        };
165
166        if let Some((local_name, raw_name, alg, is_empty)) = evt_info {
167            match local_name.as_slice() {
168                b"DigestMethod" => {
169                    r.digest_method = DigestMethod {
170                        algorithm: alg.unwrap_or_default(),
171                    };
172                    if !is_empty {
173                        parser.read_to_end(&raw_name)?;
174                    }
175                }
176                b"DigestValue" => {
177                    // Start element, read text content
178                    if !is_empty {
179                        let val = parser.read_text_content()?;
180                        r.digest_value = DigestValue { value: val };
181                    }
182                }
183                b"Transforms" => {
184                    if !is_empty {
185                        let transforms = parse_transforms_content(parser)?;
186                        r.transforms = Some(transforms);
187                    }
188                }
189                _ => {
190                    if !is_empty {
191                        parser.read_to_end(&raw_name)?;
192                    }
193                }
194            }
195        }
196    }
197}
198
199fn parse_transforms_content<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<Transform>> {
200    let mut transforms = Vec::new();
201    loop {
202        let evt_info = match parser.read_next_event()? {
203            Event::Start(e) => {
204                let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
205                Some((
206                    e.local_name().as_ref().to_vec(),
207                    e.name().as_ref().to_vec(),
208                    alg,
209                    false,
210                ))
211            }
212            Event::Empty(e) => {
213                let alg = get_attribute(&e, b"Algorithm").map(|s| s.into_owned());
214                Some((
215                    e.local_name().as_ref().to_vec(),
216                    e.name().as_ref().to_vec(),
217                    alg,
218                    true,
219                ))
220            }
221            Event::End(e) if e.local_name().as_ref() == b"Transforms" => return Ok(transforms),
222            Event::Eof => {
223                return Err(Lib3mfError::Validation(
224                    "Unexpected EOF in Transforms".to_string(),
225                ));
226            }
227            _ => None,
228        };
229
230        if let Some((local_name, raw_name, alg, is_empty)) = evt_info {
231            match local_name.as_slice() {
232                b"Transform" => {
233                    transforms.push(Transform {
234                        algorithm: alg.unwrap_or_default(),
235                    });
236                    if !is_empty {
237                        parser.read_to_end(&raw_name)?;
238                    }
239                }
240                _ => {
241                    if !is_empty {
242                        parser.read_to_end(&raw_name)?;
243                    }
244                }
245            }
246        }
247    }
248}
249
250fn parse_key_info<R: BufRead>(parser: &mut XmlParser<R>) -> Result<KeyInfo> {
251    let mut info = KeyInfo::default();
252
253    loop {
254        let evt_info = match parser.read_next_event()? {
255            Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
256            Event::End(e) if e.local_name().as_ref() == b"KeyInfo" => return Ok(info),
257            Event::Eof => {
258                return Err(Lib3mfError::Validation(
259                    "Unexpected EOF in KeyInfo".to_string(),
260                ));
261            }
262            _ => None,
263        };
264
265        if let Some((local_name, raw_name)) = evt_info {
266            match local_name.as_slice() {
267                b"KeyName" => {
268                    let val = parser.read_text_content()?;
269                    info.key_name = Some(val);
270                }
271                b"KeyValue" => {
272                    info.key_value = Some(parse_key_value(parser)?);
273                }
274                b"X509Data" => {
275                    info.x509_data = Some(parse_x509_data(parser)?);
276                }
277                _ => {
278                    parser.read_to_end(&raw_name)?;
279                }
280            }
281        }
282    }
283}
284
285fn parse_x509_data<R: BufRead>(parser: &mut XmlParser<R>) -> Result<X509Data> {
286    let mut data = X509Data::default();
287    loop {
288        let evt_info = match parser.read_next_event()? {
289            Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
290            Event::End(e) if e.local_name().as_ref() == b"X509Data" => return Ok(data),
291            Event::Eof => {
292                return Err(Lib3mfError::Validation(
293                    "Unexpected EOF in X509Data".to_string(),
294                ));
295            }
296            _ => None,
297        };
298
299        if let Some((local_name, raw_name)) = evt_info {
300            match local_name.as_slice() {
301                b"X509Certificate" => {
302                    // X509Certificate is a text string (Base64)
303                    let val = parser.read_text_content()?;
304                    // Clean up whitespace?
305                    let cleaned = val.chars().filter(|c| !c.is_whitespace()).collect();
306                    data.certificate = Some(cleaned);
307                }
308                _ => {
309                    parser.read_to_end(&raw_name)?;
310                }
311            }
312        }
313    }
314}
315
316fn parse_key_value<R: BufRead>(parser: &mut XmlParser<R>) -> Result<KeyValue> {
317    let mut val = KeyValue::default();
318    loop {
319        let evt_info = match parser.read_next_event()? {
320            Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
321            Event::End(e) if e.local_name().as_ref() == b"KeyValue" => return Ok(val),
322            Event::Eof => {
323                return Err(Lib3mfError::Validation(
324                    "Unexpected EOF in KeyValue".to_string(),
325                ));
326            }
327            _ => None,
328        };
329
330        if let Some((local_name, raw_name)) = evt_info {
331            match local_name.as_slice() {
332                b"RSAKeyValue" => {
333                    val.rsa_key_value = Some(parse_rsa_key_value(parser)?);
334                }
335                _ => {
336                    parser.read_to_end(&raw_name)?;
337                }
338            }
339        }
340    }
341}
342
343fn parse_rsa_key_value<R: BufRead>(parser: &mut XmlParser<R>) -> Result<RSAKeyValue> {
344    let mut modulus = String::new();
345    let mut exponent = String::new();
346
347    loop {
348        let evt_info = match parser.read_next_event()? {
349            Event::Start(e) => Some((e.local_name().as_ref().to_vec(), e.name().as_ref().to_vec())),
350            Event::End(e) if e.local_name().as_ref() == b"RSAKeyValue" => {
351                return Ok(RSAKeyValue { modulus, exponent });
352            }
353            Event::Eof => {
354                return Err(Lib3mfError::Validation(
355                    "Unexpected EOF in RSAKeyValue".to_string(),
356                ));
357            }
358            _ => None,
359        };
360
361        if let Some((local_name, raw_name)) = evt_info {
362            match local_name.as_slice() {
363                b"Modulus" => modulus = parser.read_text_content()?,
364                b"Exponent" => exponent = parser.read_text_content()?,
365                _ => {
366                    parser.read_to_end(&raw_name)?;
367                }
368            }
369        }
370    }
371}