pub fn contains_ds_object(signature_xml: &str) -> bool {
const XMLDSIG_NS: &str = "http://www.w3.org/2000/09/xmldsig#";
let Ok(doc) = crate::xml::parse_secure(signature_xml) else {
return false;
};
let Some(root) = doc.document_element() else {
return false;
};
for node in doc.descendants(root) {
let Some(elem) = doc.element(node) else {
continue;
};
if elem.name.local_name == "Object"
&& elem.name.namespace_uri.as_deref() == Some(XMLDSIG_NS)
{
return true;
}
}
false
}
pub const KNOWN_SIGNATURE_ALGORITHMS: &[&str] = &[
"http://www.w3.org/2000/09/xmldsig#rsa-sha1",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha224",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
"http://www.w3.org/2007/05/xmldsig-more#rsa-pss",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
"http://www.w3.org/2000/09/xmldsig#dsa-sha1",
"http://www.w3.org/2009/xmldsig11#dsa-sha256",
"http://www.w3.org/2000/09/xmldsig#hmac-sha1",
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha224",
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha256",
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha384",
"http://www.w3.org/2001/04/xmldsig-more#hmac-sha512",
];
pub fn is_known_algorithm(algorithm_uri: &str) -> bool {
KNOWN_SIGNATURE_ALGORITHMS.contains(&algorithm_uri)
}
pub const CBC_ENCRYPTION_ALGORITHMS: &[&str] = &[
"http://www.w3.org/2001/04/xmlenc#aes128-cbc",
"http://www.w3.org/2001/04/xmlenc#aes192-cbc",
"http://www.w3.org/2001/04/xmlenc#aes256-cbc",
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc",
];
pub const GCM_ENCRYPTION_ALGORITHMS: &[&str] = &[
"http://www.w3.org/2009/xmlenc11#aes128-gcm",
"http://www.w3.org/2009/xmlenc11#aes192-gcm",
"http://www.w3.org/2009/xmlenc11#aes256-gcm",
];
pub fn is_cbc_algorithm(algorithm_uri: &str) -> bool {
CBC_ENCRYPTION_ALGORITHMS.contains(&algorithm_uri)
}
pub fn is_gcm_algorithm(algorithm_uri: &str) -> bool {
GCM_ENCRYPTION_ALGORITHMS.contains(&algorithm_uri)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_contains_ds_object_with_prefix() {
let xml = r#"<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo/>
<ds:SignatureValue>abc</ds:SignatureValue>
<ds:Object>malicious content</ds:Object>
</ds:Signature>"#;
assert!(contains_ds_object(xml));
}
#[test]
fn test_contains_ds_object_without_prefix() {
let xml = r#"<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo/>
<SignatureValue>abc</SignatureValue>
<Object>malicious content</Object>
</Signature>"#;
assert!(contains_ds_object(xml));
}
#[test]
fn test_no_ds_object() {
let xml = r#"<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo/>
<ds:SignatureValue>abc</ds:SignatureValue>
<ds:KeyInfo/>
</ds:Signature>"#;
assert!(!contains_ds_object(xml));
}
#[test]
fn test_dsig_prefix_object() {
let xml = r#"<dsig:Signature xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<dsig:Object>content</dsig:Object>
</dsig:Signature>"#;
assert!(contains_ds_object(xml));
}
#[test]
fn test_self_closing_object() {
let xml = r#"<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:Object />
</ds:Signature>"#;
assert!(contains_ds_object(xml));
}
#[test]
fn test_ignores_non_dsig_object() {
let xml = r#"<Signature xmlns="urn:example:not-dsig">
<Object>application content</Object>
</Signature>"#;
assert!(!contains_ds_object(xml));
}
#[test]
fn test_dsig_object_with_unusual_prefix() {
let xml = r#"<sig:Signature xmlns:sig="http://www.w3.org/2000/09/xmldsig#">
<sig:Object>content</sig:Object>
</sig:Signature>"#;
assert!(contains_ds_object(xml));
}
#[test]
fn test_known_algorithms() {
assert!(is_known_algorithm(
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
));
assert!(is_known_algorithm(
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
));
assert!(is_known_algorithm(
"http://www.w3.org/2000/09/xmldsig#rsa-sha1"
));
assert!(!is_known_algorithm("http://example.com/unknown-algorithm"));
}
#[test]
fn test_cbc_algorithms() {
assert!(is_cbc_algorithm(
"http://www.w3.org/2001/04/xmlenc#aes128-cbc"
));
assert!(is_cbc_algorithm(
"http://www.w3.org/2001/04/xmlenc#aes256-cbc"
));
assert!(is_cbc_algorithm(
"http://www.w3.org/2001/04/xmlenc#tripledes-cbc"
));
assert!(!is_cbc_algorithm(
"http://www.w3.org/2009/xmlenc11#aes128-gcm"
));
}
#[test]
fn test_gcm_algorithms() {
assert!(is_gcm_algorithm(
"http://www.w3.org/2009/xmlenc11#aes128-gcm"
));
assert!(is_gcm_algorithm(
"http://www.w3.org/2009/xmlenc11#aes256-gcm"
));
assert!(!is_gcm_algorithm(
"http://www.w3.org/2001/04/xmlenc#aes128-cbc"
));
}
}