mirror of https://github.com/ctz/rustls
Switch back to upstream ring/webpki
No longer need webpki patches! :)
This commit is contained in:
parent
c3a1067463
commit
e65ade9d93
22
Cargo.toml
22
Cargo.toml
|
@ -9,16 +9,26 @@ homepage = "https://github.com/ctz/rustls"
|
|||
repository = "https://github.com/ctz/rustls"
|
||||
|
||||
[dependencies]
|
||||
untrusted = "0.2.0"
|
||||
ring = { version = "0.1.0", git = "https://github.com/ctz/ring", features = ["rsa_signing"] }
|
||||
|
||||
# pointed at my fork for the moment
|
||||
webpki = { version = "0.1.0", git = "https://github.com/ctz/webpki" }
|
||||
|
||||
untrusted = "0.3.1"
|
||||
time = "0.1.35"
|
||||
base64 = "~0.2.0"
|
||||
log = "0.3.6"
|
||||
|
||||
[replace]
|
||||
"ring:0.2.0" = { git = "https://github.com/briansmith/ring", rev = "ec39fbd" }
|
||||
"webpki:0.1.0" = { git = "https://github.com/briansmith/webpki", rev = "0749501" }
|
||||
|
||||
[dependencies.ring]
|
||||
git = "https://github.com/briansmith/ring"
|
||||
version = "0.2.0"
|
||||
features = [ "rsa_signing" ]
|
||||
rev = "ec39fbd"
|
||||
|
||||
[dependencies.webpki]
|
||||
git = "https://github.com/briansmith/webpki"
|
||||
version = "0.1.0"
|
||||
rev = "0749501"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.3.3"
|
||||
mio = "0.5.1"
|
||||
|
|
|
@ -253,11 +253,14 @@ impl MessageCipher for GCMMessageCipher {
|
|||
msg.version.encode(&mut aad);
|
||||
codec::encode_u16((buf.len() - GCM_OVERHEAD) as u16, &mut aad);
|
||||
|
||||
let plain_len = try!(ring::aead::open_in_place(&self.dec_key,
|
||||
&nonce,
|
||||
GCM_EXPLICIT_NONCE_LEN,
|
||||
&mut buf,
|
||||
&aad));
|
||||
let plain_len = try!(
|
||||
ring::aead::open_in_place(&self.dec_key,
|
||||
&nonce,
|
||||
GCM_EXPLICIT_NONCE_LEN,
|
||||
&mut buf,
|
||||
&aad)
|
||||
.map_err(|_| ())
|
||||
);
|
||||
|
||||
buf.truncate(plain_len);
|
||||
|
||||
|
@ -300,11 +303,14 @@ impl MessageCipher for GCMMessageCipher {
|
|||
msg.version.encode(&mut aad);
|
||||
codec::encode_u16(payload_len as u16, &mut aad);
|
||||
|
||||
try!(ring::aead::seal_in_place(&self.enc_key,
|
||||
&nonce,
|
||||
&mut buf[GCM_EXPLICIT_NONCE_LEN..],
|
||||
tag_len,
|
||||
&aad));
|
||||
try!(
|
||||
ring::aead::seal_in_place(&self.enc_key,
|
||||
&nonce,
|
||||
&mut buf[GCM_EXPLICIT_NONCE_LEN..],
|
||||
tag_len,
|
||||
&aad)
|
||||
.map_err(|_| ())
|
||||
);
|
||||
|
||||
buf[0..8].as_mut().write(&nonce[4..]).unwrap();
|
||||
|
||||
|
@ -396,11 +402,14 @@ impl MessageCipher for ChaCha20Poly1305MessageCipher {
|
|||
msg.version.encode(&mut aad);
|
||||
codec::encode_u16((buf.len() - CP_OVERHEAD) as u16, &mut aad);
|
||||
|
||||
let plain_len = try!(ring::aead::open_in_place(&self.dec_key,
|
||||
&nonce,
|
||||
0,
|
||||
&mut buf,
|
||||
&aad));
|
||||
let plain_len = try!(
|
||||
ring::aead::open_in_place(&self.dec_key,
|
||||
&nonce,
|
||||
0,
|
||||
&mut buf,
|
||||
&aad)
|
||||
.map_err(|_| ())
|
||||
);
|
||||
|
||||
buf.truncate(plain_len);
|
||||
|
||||
|
@ -433,11 +442,14 @@ impl MessageCipher for ChaCha20Poly1305MessageCipher {
|
|||
msg.version.encode(&mut aad);
|
||||
codec::encode_u16(payload_len as u16, &mut aad);
|
||||
|
||||
try!(ring::aead::seal_in_place(&self.enc_key,
|
||||
&nonce,
|
||||
&mut buf,
|
||||
tag_len,
|
||||
&aad));
|
||||
try!(
|
||||
ring::aead::seal_in_place(&self.enc_key,
|
||||
&nonce,
|
||||
&mut buf,
|
||||
tag_len,
|
||||
&aad)
|
||||
.map_err(|_| ())
|
||||
);
|
||||
|
||||
Ok(Message {
|
||||
typ: msg.typ.clone(),
|
||||
|
|
|
@ -19,7 +19,9 @@ pub struct RSASigner {
|
|||
impl RSASigner {
|
||||
pub fn new(der: &[u8]) -> Result<RSASigner, ()> {
|
||||
let key = ring::signature::RSAKeyPair::from_der(untrusted::Input::from(der));
|
||||
key.map(|k| RSASigner { key: k })
|
||||
key
|
||||
.map(|k| RSASigner { key: k })
|
||||
.map_err(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +37,7 @@ impl Signer for RSASigner {
|
|||
let rng = ring::rand::SystemRandom::new();
|
||||
self.key.sign(pad, &rng, message, &mut sig)
|
||||
.map(|_| sig)
|
||||
.map_err(|_| ())
|
||||
}
|
||||
|
||||
fn algorithm(&self) -> SignatureAlgorithm {
|
||||
|
|
115
src/verify.rs
115
src/verify.rs
|
@ -13,9 +13,11 @@ use x509;
|
|||
|
||||
use std::io;
|
||||
|
||||
type SignatureAlgorithms = &'static [&'static webpki::SignatureAlgorithm];
|
||||
|
||||
/// Which signature verification mechanisms we support. No particular
|
||||
/// order.
|
||||
static SUPPORTED_SIG_ALGS: &'static [&'static webpki::SignatureAlgorithm] = &[
|
||||
static SUPPORTED_SIG_ALGS: SignatureAlgorithms = &[
|
||||
&webpki::ECDSA_P256_SHA1,
|
||||
&webpki::ECDSA_P256_SHA256,
|
||||
&webpki::ECDSA_P256_SHA384,
|
||||
|
@ -134,14 +136,21 @@ impl RootCertStore {
|
|||
}
|
||||
|
||||
/// Check `presented_certs` is non-empty and rooted in `roots`.
|
||||
fn verify_common_cert(roots: &RootCertStore,
|
||||
presented_certs: &Vec<ASN1Cert>) -> Result<(), TLSError> {
|
||||
/// Return the webpki::EndEntityCert for the top certificate
|
||||
/// in `presented_certs`.
|
||||
fn verify_common_cert<'a>(roots: &RootCertStore,
|
||||
presented_certs: &'a [ASN1Cert])
|
||||
-> Result<webpki::EndEntityCert<'a>, TLSError> {
|
||||
if presented_certs.len() == 0 {
|
||||
return Err(TLSError::NoCertificatesPresented);
|
||||
}
|
||||
|
||||
/* EE cert must appear first. */
|
||||
let ee = untrusted::Input::from(&presented_certs[0].0);
|
||||
let cert_der = untrusted::Input::from(&presented_certs[0].0);
|
||||
let cert = try!(
|
||||
webpki::EndEntityCert::from(cert_der)
|
||||
.map_err(|err| TLSError::WebPKIError(err))
|
||||
);
|
||||
|
||||
let chain: Vec<untrusted::Input> = presented_certs.iter()
|
||||
.skip(1)
|
||||
|
@ -152,12 +161,12 @@ fn verify_common_cert(roots: &RootCertStore,
|
|||
.map(|x| x.to_trust_anchor())
|
||||
.collect();
|
||||
|
||||
webpki::verify_tls_cert(&SUPPORTED_SIG_ALGS,
|
||||
&trustroots,
|
||||
&chain,
|
||||
ee,
|
||||
time::get_time())
|
||||
cert.verify_is_valid_tls_server_cert(&SUPPORTED_SIG_ALGS,
|
||||
&trustroots,
|
||||
&chain,
|
||||
time::get_time())
|
||||
.map_err(|err| TLSError::WebPKIError(err))
|
||||
.map(|_| cert)
|
||||
}
|
||||
|
||||
/// Verify a the certificate chain `presented_certs` against the roots
|
||||
|
@ -166,13 +175,10 @@ fn verify_common_cert(roots: &RootCertStore,
|
|||
pub fn verify_server_cert(roots: &RootCertStore,
|
||||
presented_certs: &Vec<ASN1Cert>,
|
||||
dns_name: &str) -> Result<(), TLSError> {
|
||||
try!(verify_common_cert(roots, presented_certs));
|
||||
let cert = try!(verify_common_cert(roots, presented_certs));
|
||||
|
||||
webpki::verify_cert_dns_name(
|
||||
untrusted::Input::from(&presented_certs[0].0),
|
||||
untrusted::Input::from(dns_name.as_bytes())
|
||||
)
|
||||
.map_err(|err| TLSError::WebPKIError(err))
|
||||
cert.verify_is_valid_for_dns_name(untrusted::Input::from(dns_name.as_bytes()))
|
||||
.map_err(|err| TLSError::WebPKIError(err))
|
||||
}
|
||||
|
||||
/// Verify a certificate chain `presented_certs` is rooted in `roots`.
|
||||
|
@ -180,36 +186,62 @@ pub fn verify_server_cert(roots: &RootCertStore,
|
|||
pub fn verify_client_cert(roots: &RootCertStore,
|
||||
presented_certs: &Vec<ASN1Cert>) -> Result<(), TLSError> {
|
||||
verify_common_cert(roots, presented_certs)
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
/* TODO: this is a bit gross. consider doing it another way */
|
||||
static ECDSA_SHA1: &'static [u8] = b"\x06\x07\x2a\x86\x48\xce\x3d\x04\x01";
|
||||
static ECDSA_SHA256: &'static [u8] = b"\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x02";
|
||||
static ECDSA_SHA384: &'static [u8] = b"\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x03";
|
||||
static ECDSA_SHA512: &'static [u8] = b"\x06\x08\x2a\x86\x48\xce\x3d\x04\x03\x04";
|
||||
static RSA_SHA1: &'static [u8] = b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x05";
|
||||
static RSA_SHA256: &'static [u8] = b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0b";
|
||||
static RSA_SHA384: &'static [u8] = b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0c";
|
||||
static RSA_SHA512: &'static [u8] = b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x0d";
|
||||
static ECDSA_SHA1: SignatureAlgorithms = &[
|
||||
&webpki::ECDSA_P256_SHA1, &webpki::ECDSA_P384_SHA1
|
||||
];
|
||||
static ECDSA_SHA256: SignatureAlgorithms = &[
|
||||
&webpki::ECDSA_P256_SHA256, &webpki::ECDSA_P384_SHA256
|
||||
];
|
||||
static ECDSA_SHA384: SignatureAlgorithms = &[
|
||||
&webpki::ECDSA_P256_SHA384, &webpki::ECDSA_P384_SHA384
|
||||
];
|
||||
static ECDSA_SHA512: SignatureAlgorithms = &[
|
||||
&webpki::ECDSA_P256_SHA512, &webpki::ECDSA_P384_SHA512
|
||||
];
|
||||
|
||||
static RSA_SHA1: SignatureAlgorithms = &[ &webpki::RSA_PKCS1_2048_8192_SHA1 ];
|
||||
static RSA_SHA256: SignatureAlgorithms = &[ &webpki::RSA_PKCS1_2048_8192_SHA256 ];
|
||||
static RSA_SHA384: SignatureAlgorithms = &[ &webpki::RSA_PKCS1_2048_8192_SHA384 ];
|
||||
static RSA_SHA512: SignatureAlgorithms = &[ &webpki::RSA_PKCS1_2048_8192_SHA512 ];
|
||||
|
||||
fn convert_alg(sh: &SignatureAndHashAlgorithm) -> Result<&'static [u8], TLSError> {
|
||||
fn convert_alg(sh: &SignatureAndHashAlgorithm) -> Result<SignatureAlgorithms, TLSError> {
|
||||
use msgs::enums::SignatureAlgorithm::{ECDSA, RSA};
|
||||
use msgs::enums::HashAlgorithm::{SHA1, SHA256, SHA384, SHA512};
|
||||
|
||||
match (&sh.sign, &sh.hash) {
|
||||
(&ECDSA, &SHA1) => Ok(ECDSA_SHA1),
|
||||
(&ECDSA, &SHA256) => Ok(ECDSA_SHA256),
|
||||
(&ECDSA, &SHA384) => Ok(ECDSA_SHA384),
|
||||
(&ECDSA, &SHA512) => Ok(ECDSA_SHA512),
|
||||
(&RSA, &SHA1) => Ok(RSA_SHA1),
|
||||
(&RSA, &SHA256) => Ok(RSA_SHA256),
|
||||
(&RSA, &SHA384) => Ok(RSA_SHA384),
|
||||
(&RSA, &SHA512) => Ok(RSA_SHA512),
|
||||
_ => Err(TLSError::General("convert_alg cannot map to oid".to_string()))
|
||||
(&ECDSA, &SHA1) => Ok(&ECDSA_SHA1),
|
||||
(&ECDSA, &SHA256) => Ok(&ECDSA_SHA256),
|
||||
(&ECDSA, &SHA384) => Ok(&ECDSA_SHA384),
|
||||
(&ECDSA, &SHA512) => Ok(&ECDSA_SHA512),
|
||||
(&RSA, &SHA1) => Ok(&RSA_SHA1),
|
||||
(&RSA, &SHA256) => Ok(&RSA_SHA256),
|
||||
(&RSA, &SHA384) => Ok(&RSA_SHA384),
|
||||
(&RSA, &SHA512) => Ok(&RSA_SHA512),
|
||||
_ => Err(TLSError::General("cannot convert to webpki sigalg".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_sig_using_any_alg(cert: &webpki::EndEntityCert,
|
||||
algs: SignatureAlgorithms,
|
||||
message: &[u8],
|
||||
sig: &[u8]) -> Result<(), webpki::Error> {
|
||||
/* TLS doesn't itself give us enough info to map to a single webpki::SignatureAlgorithm.
|
||||
* Therefore, in convert_algs maps to several and we try them all. */
|
||||
for alg in algs {
|
||||
match cert.verify_signature(alg,
|
||||
untrusted::Input::from(message),
|
||||
untrusted::Input::from(sig)) {
|
||||
Err(webpki::Error::UnsupportedSignatureAlgorithmForPublicKey) => continue,
|
||||
res => return res
|
||||
}
|
||||
}
|
||||
|
||||
Err(webpki::Error::UnsupportedSignatureAlgorithmForPublicKey)
|
||||
}
|
||||
|
||||
/// Verify the signed `message` using the public key quoted in
|
||||
/// `cert` and algorithm and signature in `dss`.
|
||||
///
|
||||
|
@ -219,21 +251,12 @@ pub fn verify_signed_struct(message: &[u8],
|
|||
cert: &ASN1Cert,
|
||||
dss: &DigitallySignedStruct) -> Result<(), TLSError> {
|
||||
|
||||
let alg = try!(convert_alg(&dss.alg));
|
||||
|
||||
let signed_data = webpki::signed_data::SignedData {
|
||||
data: untrusted::Input::from(message),
|
||||
algorithm: untrusted::Input::from(alg),
|
||||
signature: untrusted::Input::from(&dss.sig.0)
|
||||
};
|
||||
|
||||
let possible_algs = try!(convert_alg(&dss.alg));
|
||||
let cert_in = untrusted::Input::from(&cert.0);
|
||||
let cert = try!(webpki::trust_anchor_util::cert_der_as_trust_anchor(cert_in)
|
||||
let cert = try!(webpki::EndEntityCert::from(cert_in)
|
||||
.map_err(|err| TLSError::WebPKIError(err)));
|
||||
|
||||
webpki::signed_data::verify_signed_data(&SUPPORTED_SIG_ALGS,
|
||||
untrusted::Input::from(cert.spki),
|
||||
&signed_data)
|
||||
verify_sig_using_any_alg(&cert, &possible_algs, message, &dss.sig.0)
|
||||
.map_err(|err| TLSError::WebPKIError(err))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue