1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use msgs::enums::{SignatureAlgorithm, SignatureScheme};
use util;
use untrusted;
use ring;
use ring::signature;
use std::sync::Arc;
use key;

/// A thing that can sign a message.
pub trait Signer : Send + Sync {
    /// Choose a SignatureScheme from those offered.
    fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<SignatureScheme>;

    /// Signs `message` using `scheme`.
    fn sign(&self, scheme: SignatureScheme, message: &[u8]) -> Result<Vec<u8>, ()>;

    /// What kind of key we have.
    fn algorithm(&self) -> SignatureAlgorithm;
}

pub type CertChainAndSigner = (Vec<key::Certificate>, Arc<Box<Signer>>);

/// A Signer for RSA-PKCS1 or RSA-PSS
pub struct RSASigner {
    key: Arc<signature::RSAKeyPair>,
    schemes: Vec<SignatureScheme>,
}

fn all_schemes() -> Vec<SignatureScheme> {
    vec![SignatureScheme::RSA_PSS_SHA512,
         SignatureScheme::RSA_PSS_SHA384,
         SignatureScheme::RSA_PSS_SHA256,
         SignatureScheme::RSA_PKCS1_SHA512,
         SignatureScheme::RSA_PKCS1_SHA384,
         SignatureScheme::RSA_PKCS1_SHA256]
}

impl RSASigner {
    pub fn new(der: &key::PrivateKey) -> Result<RSASigner, ()> {
        let key = signature::RSAKeyPair::from_der(untrusted::Input::from(&der.0));
        key.map(|s| {
                RSASigner {
                    key: Arc::new(s),
                    schemes: all_schemes(),
                }
            })
            .map_err(|_| ())
    }
}

impl Signer for RSASigner {
    fn choose_scheme(&self, offered: &[SignatureScheme]) -> Option<SignatureScheme> {
        util::first_in_both(&self.schemes, offered)
    }

    fn sign(&self, scheme: SignatureScheme, message: &[u8]) -> Result<Vec<u8>, ()> {
        let mut sig = vec![0; self.key.public_modulus_len()];

        let encoding: &signature::RSAEncoding = match scheme {
            SignatureScheme::RSA_PKCS1_SHA256 => &signature::RSA_PKCS1_SHA256,
            SignatureScheme::RSA_PKCS1_SHA384 => &signature::RSA_PKCS1_SHA384,
            SignatureScheme::RSA_PKCS1_SHA512 => &signature::RSA_PKCS1_SHA512,
            SignatureScheme::RSA_PSS_SHA256 => &signature::RSA_PSS_SHA256,
            SignatureScheme::RSA_PSS_SHA384 => &signature::RSA_PSS_SHA384,
            SignatureScheme::RSA_PSS_SHA512 => &signature::RSA_PSS_SHA512,
            _ => return Err(()),
        };

        let rng = ring::rand::SystemRandom::new();
        let mut signer = try!(signature::RSASigningState::new(self.key.clone()).map_err(|_| ()));

        signer.sign(encoding, &rng, message, &mut sig)
            .map(|_| sig)
            .map_err(|_| ())
    }

    fn algorithm(&self) -> SignatureAlgorithm {
        SignatureAlgorithm::RSA
    }
}