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