Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/xmldsig/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub use transforms::{
};
pub use types::{NodeSet, TransformData, TransformError};
pub use verify::{
DsigStatus, FailureReason, KeyResolver, ReferenceProcessingError, ReferenceResult,
ReferencesResult, SignatureVerificationPipelineError, UriTypeSet, VerifyContext, VerifyResult,
VerifyingKey, process_all_references, process_reference, verify_signature_with_pem_key,
DsigError, DsigStatus, FailureReason, KeyResolver, ReferenceProcessingError, ReferenceResult,
ReferencesResult, UriTypeSet, VerifyContext, VerifyResult, VerifyingKey,
process_all_references, process_reference, verify_signature_with_pem_key,
};
6 changes: 2 additions & 4 deletions src/xmldsig/transforms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,7 @@ pub(crate) fn apply_transform<'a>(
let nodes = input.into_node_set()?;
let mut output = Vec::new();
let predicate = |node: Node| nodes.contains(node);
c14n::canonicalize(nodes.document(), Some(&predicate), algo, &mut output)
.map_err(|e| TransformError::C14n(e.to_string()))?;
c14n::canonicalize(nodes.document(), Some(&predicate), algo, &mut output)?;
Ok(TransformData::Binary(output))
}
}
Expand Down Expand Up @@ -142,8 +141,7 @@ pub fn execute_transforms<'a>(
.expect("default C14N algorithm URI must be supported by C14nAlgorithm::from_uri");
let mut output = Vec::new();
let predicate = |node: Node| nodes.contains(node);
c14n::canonicalize(nodes.document(), Some(&predicate), &algo, &mut output)
.map_err(|e| TransformError::C14n(e.to_string()))?;
c14n::canonicalize(nodes.document(), Some(&predicate), &algo, &mut output)?;
Ok(output)
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/xmldsig/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ pub enum TransformError {

/// Canonicalization error during transform.
#[error("C14N error: {0}")]
C14n(String),
C14n(#[from] crate::c14n::C14nError),

/// The Signature node passed to the enveloped transform belongs to a
/// different `Document` than the input `NodeSet`.
Expand Down
21 changes: 10 additions & 11 deletions src/xmldsig/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub trait VerifyingKey {
algorithm: SignatureAlgorithm,
signed_data: &[u8],
signature_value: &[u8],
) -> Result<bool, SignatureVerificationPipelineError>;
) -> Result<bool, DsigError>;
}

/// Key resolver hook used by [`VerifyContext`] when no pre-set key is provided.
Expand All @@ -55,10 +55,7 @@ pub trait KeyResolver {
/// key material (for example, missing `<KeyInfo>` candidates). `VerifyContext`
/// maps `Ok(None)` to `DsigStatus::Invalid(FailureReason::KeyNotFound)`;
/// reserve `Err(...)` for resolver failures.
fn resolve<'a>(
&'a self,
xml: &str,
) -> Result<Option<Box<dyn VerifyingKey + 'a>>, SignatureVerificationPipelineError>;
fn resolve<'a>(&'a self, xml: &str) -> Result<Option<Box<dyn VerifyingKey + 'a>>, DsigError>;
}

/// Allowed URI classes for `<Reference URI="...">`.
Expand Down Expand Up @@ -212,7 +209,7 @@ impl<'a> VerifyContext<'a> {
/// Returns `Ok(VerifyResult)` for both valid and invalid signatures; inspect
/// `VerifyResult::status` for the verification outcome. `Err(...)` is
/// reserved for pipeline failures.
pub fn verify(&self, xml: &str) -> Result<VerifyResult, SignatureVerificationPipelineError> {
pub fn verify(&self, xml: &str) -> Result<VerifyResult, DsigError> {
verify_signature_with_context(xml, self)
}
}
Expand Down Expand Up @@ -394,11 +391,11 @@ pub enum ReferenceProcessingError {

/// URI dereference failed.
#[error("URI dereference failed: {0}")]
UriDereference(super::types::TransformError),
UriDereference(#[source] super::types::TransformError),

/// Transform execution failed.
#[error("transform failed: {0}")]
Transform(super::types::TransformError),
Transform(#[source] super::types::TransformError),
}

/// End-to-end XMLDSig verification result for one `<Signature>`.
Expand All @@ -422,7 +419,7 @@ pub struct VerifyResult {
/// Errors while running end-to-end XMLDSig verification.
#[derive(Debug, thiserror::Error)]
#[non_exhaustive]
pub enum SignatureVerificationPipelineError {
pub enum DsigError {
/// XML parsing failed.
#[error("XML parse error: {0}")]
XmlParse(#[from] roxmltree::Error),
Expand Down Expand Up @@ -480,6 +477,8 @@ pub enum SignatureVerificationPipelineError {
ManifestProcessingUnsupported,
}

type SignatureVerificationPipelineError = DsigError;

/// Verify one XMLDSig `<Signature>` end-to-end with a PEM public key.
///
/// Pipeline:
Expand All @@ -501,7 +500,7 @@ pub fn verify_signature_with_pem_key(
xml: &str,
public_key_pem: &str,
store_pre_digest: bool,
) -> Result<VerifyResult, SignatureVerificationPipelineError> {
) -> Result<VerifyResult, DsigError> {
struct PemVerifyingKey<'a> {
public_key_pem: &'a str,
}
Expand All @@ -512,7 +511,7 @@ pub fn verify_signature_with_pem_key(
algorithm: SignatureAlgorithm,
signed_data: &[u8],
signature_value: &[u8],
) -> Result<bool, SignatureVerificationPipelineError> {
) -> Result<bool, DsigError> {
verify_with_algorithm(algorithm, self.public_key_pem, signed_data, signature_value)
}
}
Expand Down
29 changes: 9 additions & 20 deletions tests/signature_pipeline_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@

use std::path::Path;

use xml_sec::xmldsig::{
DsigStatus, FailureReason, SignatureVerificationPipelineError, verify_signature_with_pem_key,
};
use xml_sec::xmldsig::{DsigError, DsigStatus, FailureReason, verify_signature_with_pem_key};

fn read_fixture(path: &Path) -> String {
std::fs::read_to_string(path)
Expand Down Expand Up @@ -93,12 +91,9 @@ fn strip_xml_declaration(xml: &str) -> &str {
xml
}

fn assert_invalid_structure_reason(
err: SignatureVerificationPipelineError,
expected_reason: &'static str,
) {
fn assert_invalid_structure_reason(err: DsigError, expected_reason: &'static str) {
match err {
SignatureVerificationPipelineError::InvalidStructure { reason } => {
DsigError::InvalidStructure { reason } => {
assert_eq!(reason, expected_reason);
}
other => panic!("expected InvalidStructure error, got: {other:?}"),
Expand Down Expand Up @@ -411,10 +406,7 @@ fn malformed_signature_value_base64_returns_decode_error() {
let err = verify_signature_with_pem_key(&tampered_xml, &public_key_pem, false)
.expect_err("malformed SignatureValue base64 must fail decode stage");

assert!(matches!(
err,
SignatureVerificationPipelineError::SignatureValueBase64(_)
));
assert!(matches!(err, DsigError::SignatureValueBase64(_)));
}

#[test]
Expand All @@ -428,10 +420,7 @@ fn signature_value_with_non_ascii_whitespace_is_rejected() {
let err = verify_signature_with_pem_key(&tampered_xml, &public_key_pem, false)
.expect_err("non-XML whitespace in SignatureValue must fail base64 decode");

assert!(matches!(
err,
SignatureVerificationPipelineError::SignatureValueBase64(_)
));
assert!(matches!(err, DsigError::SignatureValueBase64(_)));
}

#[test]
Expand Down Expand Up @@ -494,7 +483,7 @@ fn missing_signed_info_is_reported_as_missing_element() {
.expect_err("missing SignedInfo must be rejected as missing element");
assert!(matches!(
err,
SignatureVerificationPipelineError::MissingElement {
DsigError::MissingElement {
element: "SignedInfo"
}
));
Expand All @@ -512,7 +501,7 @@ fn non_empty_signature_without_signed_info_is_reported_as_missing_element() {
.expect_err("non-empty Signature without SignedInfo must be rejected as missing element");
assert!(matches!(
err,
SignatureVerificationPipelineError::MissingElement {
DsigError::MissingElement {
element: "SignedInfo"
}
));
Expand All @@ -531,7 +520,7 @@ fn signature_value_only_without_signed_info_reports_missing_element() {
.expect_err("Signature without SignedInfo must report missing SignedInfo");
assert!(matches!(
err,
SignatureVerificationPipelineError::MissingElement {
DsigError::MissingElement {
element: "SignedInfo"
}
));
Expand All @@ -552,7 +541,7 @@ fn multiple_signature_elements_are_rejected() {
.expect_err("documents with multiple Signature elements must be rejected");
assert!(matches!(
err,
SignatureVerificationPipelineError::InvalidStructure {
DsigError::InvalidStructure {
reason: "Signature must appear exactly once in document",
}
));
Expand Down
Loading