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