1#![doc = include_str!("../../docs/xmlenc.md")]
14
15use roxmltree::Node;
16
17mod decrypt;
18mod encrypt;
19mod parse;
20mod types;
21
22pub use decrypt::{
23 DecryptContext, DecryptionKeyResolver, DocumentDecryptionOptions, KekDecryptor,
24 KeyCandidateBudget, PrivateKeyDecryptor, SymmetricKeyDecryptor, decrypt, decrypt_data,
25 decrypt_document, decrypt_document_with_options,
26};
27pub use encrypt::{
28 EncryptedDataBuilder, validate_key_transport_recipient, validate_rsa_recipient_key,
29};
30pub use parse::{
31 parse_encrypted_data, parse_encrypted_data_node_with_policy,
32 parse_encrypted_data_template_node_with_policy,
33};
34pub use types::{
35 CipherData, DataEncryptionAlgorithm, DecryptedContent, DocumentEncryptionOptions,
36 EncryptedData, EncryptedDataType, EncryptedKey, EncryptionMethod, EncryptionRecipient,
37 EncryptionResult, KeyTransportAlgorithm, KeyWrapAlgorithm, OaepDigestAlgorithm, ReferenceList,
38 ReplacementMode, RsaOaepParameters, XmlEncError,
39};
40
41fn map_document_error(
42 error: crate::document::XmlDocumentError,
43 settings: crate::document::DocumentParseSettings,
44) -> XmlEncError {
45 match error.into_policy_violation(settings) {
46 Ok(error) => XmlEncError::Policy(error),
47 Err(crate::document::XmlDocumentError::Parse(error)) => XmlEncError::XmlParse(error),
48 Err(crate::document::XmlDocumentError::ProjectedNodeLimit { maximum }) => {
49 crate::policy::PolicyViolation::ResourceLimit {
50 resource: crate::policy::resource_name::XML_NODES,
51 maximum,
52 actual: maximum.saturating_add(1),
53 }
54 .into()
55 }
56 Err(error) => XmlEncError::Document(error),
57 }
58}
59
60fn has_single_element_with_boundary_trivia(parent: Node<'_, '_>) -> bool {
61 let mut element_count = 0;
62 for node in parent.children() {
63 if node.is_element() {
64 element_count += 1;
65 if element_count > 1 {
66 return false;
67 }
68 } else if node.is_comment() {
69 continue;
70 } else if node.is_text() {
71 if !node.text().is_some_and(|text| {
74 text.chars()
75 .all(|character| matches!(character, ' ' | '\t' | '\n' | '\r'))
76 }) {
77 return false;
78 }
79 } else {
80 return false;
81 }
82 }
83 element_count == 1
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::document::{DocumentParseSettings, XmlDocumentError};
90
91 #[test]
92 fn document_errors_have_one_xmlenc_policy_mapping() {
93 let settings = DocumentParseSettings::new_with_depth(false, 8, 3, 128);
96 assert!(matches!(
97 map_document_error(
98 XmlDocumentError::DocumentTooDeep {
99 maximum: 3,
100 actual: 4,
101 },
102 settings,
103 ),
104 XmlEncError::Policy(crate::policy::PolicyViolation::ResourceLimit {
105 resource: crate::policy::resource_name::XML_DEPTH,
106 maximum: 3,
107 actual: 4,
108 })
109 ));
110 assert!(matches!(
111 map_document_error(
112 XmlDocumentError::ProjectedNodeLimit { maximum: 8 },
113 settings,
114 ),
115 XmlEncError::Policy(crate::policy::PolicyViolation::ResourceLimit {
116 resource: crate::policy::resource_name::XML_NODES,
117 maximum: 8,
118 actual: 9,
119 })
120 ));
121 }
122}