lib3mf_core/parser/
secure_content_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::{AccessRight, Consumer, KeyStore, ResourceDataGroup};
3use crate::parser::xml_parser::{XmlParser, get_attribute};
4use base64::prelude::*;
5use quick_xml::events::Event;
6use std::borrow::Cow;
7use std::io::BufRead;
8
9pub fn parse_keystore_content<R: BufRead>(
10    parser: &mut XmlParser<R>,
11    uuid: uuid::Uuid,
12) -> Result<KeyStore> {
13    let mut store = KeyStore {
14        uuid,
15        ..Default::default()
16    };
17
18    loop {
19        match parser.read_next_event()? {
20            Event::Start(e) => {
21                let local_name = e.local_name();
22                match local_name.as_ref() {
23                    b"consumer" => {
24                        let id = get_attribute(&e, b"consumerid")
25                            .ok_or(Lib3mfError::Validation("Missing consumerid".to_string()))?
26                            .into_owned();
27                        let key_id = get_attribute(&e, b"keyid").map(|s: Cow<str>| s.into_owned());
28                        let key_value =
29                            get_attribute(&e, b"keyvalue").map(|s: Cow<str>| s.into_owned());
30
31                        store.consumers.push(Consumer {
32                            id,
33                            key_id,
34                            key_value,
35                        });
36
37                        let end_tag = e.name().as_ref().to_vec();
38                        parser.read_to_end(&end_tag)?;
39                    }
40                    b"resourcedatagroup" => {
41                        let key_uuid_str = get_attribute(&e, b"keyuuid")
42                            .ok_or(Lib3mfError::Validation("Missing keyuuid".to_string()))?;
43                        let key_uuid = uuid::Uuid::parse_str(&key_uuid_str).map_err(|_| {
44                            Lib3mfError::Validation(format!("Invalid keyuuid: {}", key_uuid_str))
45                        })?;
46                        let group = parse_resource_data_group(parser, key_uuid)?;
47                        store.resource_data_groups.push(group);
48                    }
49                    _ => {
50                        let end_tag = e.name().as_ref().to_vec();
51                        parser.read_to_end(&end_tag)?;
52                    }
53                }
54            }
55            Event::End(e) if e.local_name().as_ref() == b"keystore" => break,
56            Event::Eof => {
57                return Err(Lib3mfError::Validation(
58                    "Unexpected EOF in keystore".to_string(),
59                ));
60            }
61            _ => {}
62        }
63    }
64    Ok(store)
65}
66
67fn parse_resource_data_group<R: BufRead>(
68    parser: &mut XmlParser<R>,
69    key_uuid: uuid::Uuid,
70) -> Result<ResourceDataGroup> {
71    let mut group = ResourceDataGroup {
72        key_uuid,
73        access_rights: Vec::new(),
74    };
75
76    loop {
77        match parser.read_next_event()? {
78            Event::Start(e) => {
79                match e.local_name().as_ref() {
80                    b"accessright" => {
81                        let consumer_id = get_attribute(&e, b"consumerid")
82                            .ok_or(Lib3mfError::Validation("Missing consumerid".to_string()))?
83                            .into_owned();
84                        // Parse children (wrappedkey)
85                        let (wrapped_key, algorithm) = parse_access_right_content(parser)?;
86
87                        group.access_rights.push(AccessRight {
88                            consumer_id,
89                            algorithm,
90                            wrapped_key,
91                        });
92                    }
93                    _ => {
94                        let end_tag = e.name().as_ref().to_vec();
95                        parser.read_to_end(&end_tag)?;
96                    }
97                }
98            }
99            Event::End(e) if e.local_name().as_ref() == b"resourcedatagroup" => break,
100            Event::Eof => {
101                return Err(Lib3mfError::Validation(
102                    "Unexpected EOF in resourcedatagroup".to_string(),
103                ));
104            }
105            _ => {}
106        }
107    }
108    Ok(group)
109}
110
111fn parse_access_right_content<R: BufRead>(parser: &mut XmlParser<R>) -> Result<(Vec<u8>, String)> {
112    let mut wrapped_key = Vec::new();
113    let mut algorithm = "RSA-OAEP".to_string(); // Default or extracted
114
115    loop {
116        match parser.read_next_event()? {
117            Event::Start(e) => {
118                match e.local_name().as_ref() {
119                    b"wrappedkey" => {
120                        // Attribute "algorithm" might be here?
121                        if let Some(alg) = get_attribute(&e, b"encryptionalgorithm") {
122                            algorithm = alg.into_owned();
123                        }
124
125                        let text = parser.read_text_content()?;
126                        // Decode base64 to actual encrypted key bytes
127                        wrapped_key = BASE64_STANDARD.decode(text.as_bytes()).map_err(|e| {
128                            Lib3mfError::Validation(format!("Invalid base64 wrapped key: {}", e))
129                        })?;
130                    }
131                    _ => {
132                        let end_tag = e.name().as_ref().to_vec();
133                        parser.read_to_end(&end_tag)?;
134                    }
135                }
136            }
137            Event::End(e) if e.local_name().as_ref() == b"accessright" => break,
138            Event::Eof => {
139                return Err(Lib3mfError::Validation(
140                    "Unexpected EOF in accessright".to_string(),
141                ));
142            }
143            _ => {}
144        }
145    }
146    Ok((wrapped_key, algorithm))
147}