1
//! Convenience implementation of a SelfSigned object.
2

            
3
use tor_llcrypto::pk::{self, ValidatableSignature};
4

            
5
/// A SignatureGated object is a self-signed object that's well-signed
6
/// when one or more ValidatableSignature objects are correct.
7
pub struct SignatureGated<T> {
8
    /// The underlying object, which we only want to expose if the
9
    /// signature(s) are right.
10
    obj: T,
11
    /// A list of ValidatableSignature; these all must be valid, or the
12
    /// underlying object is incorrect.
13
    signatures: Vec<Box<dyn ValidatableSignature>>,
14
}
15

            
16
impl<T> SignatureGated<T> {
17
    /// Return a new SignatureGated object that will be treated as
18
    /// correct if every one if the given set of signatures is valid.
19
67
    pub fn new(obj: T, signatures: Vec<Box<dyn ValidatableSignature>>) -> Self {
20
67
        SignatureGated { obj, signatures }
21
67
    }
22
}
23

            
24
impl<T> super::SelfSigned<T> for SignatureGated<T> {
25
    type Error = signature::Error;
26
62
    fn dangerously_assume_wellsigned(self) -> T {
27
62
        self.obj
28
62
    }
29
64
    fn is_well_signed(&self) -> Result<(), Self::Error> {
30
64
        if pk::validate_all_sigs(&self.signatures[..]) {
31
62
            Ok(())
32
        } else {
33
2
            Err(signature::Error::new())
34
        }
35
64
    }
36
}
37

            
38
#[cfg(test)]
39
mod test {
40
    #![allow(clippy::unwrap_used)]
41
    use super::*;
42
    use crate::SelfSigned;
43
    use tor_llcrypto::pk::ValidatableSignature;
44

            
45
    struct BadSig;
46
    struct GoodSig;
47
    impl ValidatableSignature for BadSig {
48
        fn is_valid(&self) -> bool {
49
            false
50
        }
51
    }
52
    impl ValidatableSignature for GoodSig {
53
        fn is_valid(&self) -> bool {
54
            true
55
        }
56
    }
57

            
58
    #[test]
59
    fn test_sig_gated() {
60
        // no signature objects means it's valid
61
        let sg = SignatureGated::new(3_u32, Vec::new());
62
        assert_eq!(sg.check_signature().unwrap(), 3_u32);
63

            
64
        // any bad signature means it's bad.
65
        let sg = SignatureGated::new(77_u32, vec![Box::new(BadSig)]);
66
        assert!(sg.check_signature().is_err());
67
        let sg = SignatureGated::new(
68
            77_u32,
69
            vec![Box::new(GoodSig), Box::new(BadSig), Box::new(GoodSig)],
70
        );
71
        assert!(sg.check_signature().is_err());
72

            
73
        // All good signatures means it's good.
74
        let sg = SignatureGated::new(103_u32, vec![Box::new(GoodSig)]);
75
        assert_eq!(sg.check_signature().unwrap(), 103_u32);
76
        let sg = SignatureGated::new(
77
            104_u32,
78
            vec![Box::new(GoodSig), Box::new(GoodSig), Box::new(GoodSig)],
79
        );
80
        assert_eq!(sg.check_signature().unwrap(), 104_u32);
81
    }
82
}