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