mirror of https://github.com/ctz/rustls
work towards decoding serverkx
replace rand crate with existing ring code
This commit is contained in:
parent
b802430174
commit
e72f28a584
|
@ -3,7 +3,6 @@ name = "rustls"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.1.0 (git+https://github.com/briansmith/ring)",
|
||||
]
|
||||
|
||||
|
@ -91,7 +90,46 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.1.31"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-bigint 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -105,9 +143,9 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/briansmith/ring#b78a8d06d29a3a724b0f2cf857d35acb8d376bd2"
|
||||
source = "git+https://github.com/briansmith/ring#a3d5424a78b200a92a5fcc06f57c72e03dee90ad"
|
||||
dependencies = [
|
||||
"num 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
|
|
@ -6,4 +6,3 @@ authors = ["Joseph Birr-Pixton <jpixton@gmail.com>"]
|
|||
[dependencies]
|
||||
ring = { version = "0.1.0", git = "https://github.com/briansmith/ring" }
|
||||
mio = "0.5.1"
|
||||
rand = "0.3"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use msgs::enums::CipherSuite;
|
||||
use session::SessionSecrets;
|
||||
use suites::{SupportedCipherSuite, DEFAULT_CIPHERSUITES};
|
||||
use suites::{SupportedCipherSuite, DEFAULT_CIPHERSUITES, KeyExchangeData};
|
||||
use msgs::handshake::{SessionID, CertificatePayload};
|
||||
use msgs::handshake::{ServerNameRequest, SupportedSignatureAlgorithms};
|
||||
use msgs::handshake::{ClientExtension};
|
||||
|
@ -8,15 +8,13 @@ use msgs::deframer::MessageDeframer;
|
|||
use msgs::message::Message;
|
||||
use client_hs;
|
||||
use handshake::HandshakeError;
|
||||
use rand;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
extern crate rand;
|
||||
use self::rand::Rng;
|
||||
|
||||
pub struct ClientConfig {
|
||||
/* List of ciphersuites, in preference order. */
|
||||
pub ciphersuites: Vec<&'static SupportedCipherSuite>
|
||||
|
@ -35,6 +33,7 @@ pub struct ClientHandshakeData {
|
|||
pub ciphersuite: Option<&'static SupportedCipherSuite>,
|
||||
pub client_random: Vec<u8>,
|
||||
pub server_random: Vec<u8>,
|
||||
pub kx_data: KeyExchangeData,
|
||||
pub secrets: SessionSecrets
|
||||
}
|
||||
|
||||
|
@ -45,18 +44,13 @@ impl ClientHandshakeData {
|
|||
ciphersuite: None,
|
||||
client_random: Vec::new(),
|
||||
server_random: Vec::new(),
|
||||
kx_data: KeyExchangeData::Invalid,
|
||||
secrets: SessionSecrets::for_client()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_client_random(&mut self) {
|
||||
let mut rng = rand::thread_rng();
|
||||
self.client_random.resize(32, 0);
|
||||
rng.fill_bytes(&mut self.client_random);
|
||||
}
|
||||
|
||||
pub fn init_with_cs(&mut self, cs: &'static SupportedCipherSuite) -> bool {
|
||||
|
||||
rand::fill_random_vec(&mut self.client_random, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,10 +102,15 @@ impl ClientSession {
|
|||
ret
|
||||
}
|
||||
|
||||
pub fn find_cipher_suite(&self, suite: &CipherSuite) -> Option<SupportedCipherSuite> {
|
||||
pub fn find_cipher_suite(&self, suite: &CipherSuite) -> Option<&'static SupportedCipherSuite> {
|
||||
let got = suite.clone();
|
||||
self.config.ciphersuites.iter()
|
||||
.find(|ics| ics.suite == got)
|
||||
for ref scs in &self.config.ciphersuites {
|
||||
if scs.suite == got {
|
||||
return Some(scs);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn add_extensions(&self, exts: &mut Vec<ClientExtension>) {
|
||||
|
|
|
@ -92,11 +92,7 @@ fn ExpectServerHello_handle(sess: &mut ClientSession, m: &Message) -> Result<Con
|
|||
return Err(HandshakeError::General("server chose non-offered ciphersuite".to_string()));
|
||||
}
|
||||
|
||||
if !sess.handshake_data.init_with_cs(scs.unwrap()) {
|
||||
return Err(HandshakeError::General("failed to init our ciphersuite data".to_string()));
|
||||
}
|
||||
|
||||
/* TODO: we can send a ClientKeyExchange now */
|
||||
sess.handshake_data.ciphersuite = scs;
|
||||
|
||||
Ok(ConnState::ExpectCertificate)
|
||||
}
|
||||
|
@ -134,9 +130,14 @@ fn ExpectServerKX_expect() -> Expectation {
|
|||
}
|
||||
|
||||
fn ExpectServerKX_handle(sess: &mut ClientSession, m: &Message) -> Result<ConnState, HandshakeError> {
|
||||
let kx = extract_handshake!(m, HandshakePayload::ServerKeyExchange).unwrap();
|
||||
let opaque_kx = extract_handshake!(m, HandshakePayload::ServerKeyExchange).unwrap();
|
||||
let maybe_decoded_kx = opaque_kx.unwrap_given_kxa(&sess.handshake_data.ciphersuite.unwrap().kx);
|
||||
|
||||
println!("we have serverkx {:?}", kx);
|
||||
if maybe_decoded_kx.is_none() {
|
||||
return Err(HandshakeError::General("cannot decode server's kx".to_string()));
|
||||
}
|
||||
|
||||
println!("we have serverkx {:?}", maybe_decoded_kx);
|
||||
/* TODO: check signature by subject pubkey on this struct */
|
||||
Ok(ConnState::ExpectServerHelloDone)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ pub mod msgs;
|
|||
use msgs::codec::Reader;
|
||||
use msgs::message::Message;
|
||||
|
||||
mod rand;
|
||||
mod session;
|
||||
pub mod server;
|
||||
pub mod client;
|
||||
|
|
|
@ -1966,3 +1966,43 @@ impl HeartbeatMode {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum ECCurveType {
|
||||
ExplicitPrime,
|
||||
ExplicitChar2,
|
||||
NamedCurve,
|
||||
Unknown(u8)
|
||||
}
|
||||
|
||||
impl Codec for ECCurveType {
|
||||
fn encode(&self, bytes: &mut Vec<u8>) {
|
||||
encode_u8(self.get_u8(), bytes);
|
||||
}
|
||||
|
||||
fn read(r: &mut Reader) -> Option<ECCurveType> {
|
||||
let u = read_u8(r);
|
||||
|
||||
if u.is_none() {
|
||||
return None
|
||||
}
|
||||
|
||||
Some(match u.unwrap() {
|
||||
0x01 => ECCurveType::ExplicitPrime,
|
||||
0x02 => ECCurveType::ExplicitChar2,
|
||||
0x03 => ECCurveType::NamedCurve,
|
||||
x => ECCurveType::Unknown(x)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ECCurveType {
|
||||
pub fn get_u8(&self) -> u8 {
|
||||
match *self {
|
||||
ECCurveType::ExplicitPrime => 0x01,
|
||||
ECCurveType::ExplicitChar2 => 0x02,
|
||||
ECCurveType::NamedCurve => 0x03,
|
||||
ECCurveType::Unknown(v) => v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use msgs::enums::{ProtocolVersion, HandshakeType};
|
||||
use msgs::enums::{CipherSuite, Compression, ExtensionType, ECPointFormat, NamedCurve};
|
||||
use msgs::enums::{HashAlgorithm, SignatureAlgorithm, HeartbeatMode, ServerNameType};
|
||||
use msgs::enums::{ECCurveType};
|
||||
use msgs::base::{Payload, PayloadU8, PayloadU24};
|
||||
use msgs::codec;
|
||||
use msgs::codec::{Codec, Reader};
|
||||
|
@ -526,14 +527,100 @@ impl Codec for CertificatePayload {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum KeyExchangeAlgorithm {
|
||||
DHE_DSS,
|
||||
DHE_RSA,
|
||||
DH_ANON,
|
||||
RSA,
|
||||
DH_DSS,
|
||||
DH_RSA,
|
||||
ECDH_ECDSA,
|
||||
ECDHE_ECDSA,
|
||||
ECDH_RSA,
|
||||
ECDHE_RSA,
|
||||
ECDH_anon
|
||||
}
|
||||
|
||||
/* We don't support arbitrary curves. It's a terrible
|
||||
* idea and unnecessary attack surface. Please,
|
||||
* get a grip. */
|
||||
#[derive(Debug)]
|
||||
pub struct ECParameters {
|
||||
curve_type: ECCurveType,
|
||||
named_curve: NamedCurve
|
||||
}
|
||||
|
||||
impl Codec for ECParameters {
|
||||
fn encode(&self, bytes: &mut Vec<u8>) {
|
||||
self.curve_type.encode(bytes);
|
||||
self.named_curve.encode(bytes);
|
||||
}
|
||||
|
||||
fn read(r: &mut Reader) -> Option<ECParameters> {
|
||||
let ct = try_ret!(ECCurveType::read(r));
|
||||
|
||||
if ct != ECCurveType::NamedCurve {
|
||||
return None;
|
||||
}
|
||||
|
||||
let nc = try_ret!(NamedCurve::read(r));
|
||||
|
||||
Some(ECParameters { curve_type: ct, named_curve: nc })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ServerECDHParams {
|
||||
pub curve_params: ECParameters,
|
||||
pub public: PayloadU8
|
||||
}
|
||||
|
||||
impl Codec for ServerECDHParams {
|
||||
fn encode(&self, bytes: &mut Vec<u8>) {
|
||||
self.curve_params.encode(bytes);
|
||||
self.public.encode(bytes);
|
||||
}
|
||||
|
||||
fn read(r: &mut Reader) -> Option<ServerECDHParams> {
|
||||
let cp = try_ret!(ECParameters::read(r));
|
||||
let pb = try_ret!(PayloadU8::read(r));
|
||||
|
||||
Some(ServerECDHParams { curve_params: cp, public: pb })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ECDHEServerKeyExchange {
|
||||
pub params: ServerECDHParams,
|
||||
pub sig: Vec<u8>
|
||||
}
|
||||
|
||||
impl Codec for ECDHEServerKeyExchange {
|
||||
fn encode(&self, bytes: &mut Vec<u8>) {
|
||||
self.params.encode(bytes);
|
||||
bytes.extend(self.sig.iter());
|
||||
}
|
||||
|
||||
fn read(r: &mut Reader) -> Option<ECDHEServerKeyExchange> {
|
||||
let params = try_ret!(ServerECDHParams::read(r));
|
||||
let mut sig = Vec::new();
|
||||
sig.extend_from_slice(r.rest());
|
||||
|
||||
Some(ECDHEServerKeyExchange { params: params, sig: sig })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ServerKeyExchangePayload {
|
||||
ECDHE(ECDHEServerKeyExchange),
|
||||
Unknown(Payload)
|
||||
}
|
||||
|
||||
impl Codec for ServerKeyExchangePayload {
|
||||
fn encode(&self, bytes: &mut Vec<u8>) {
|
||||
match *self {
|
||||
ServerKeyExchangePayload::ECDHE(ref x) => x.encode(bytes),
|
||||
ServerKeyExchangePayload::Unknown(ref x) => x.encode(bytes)
|
||||
}
|
||||
}
|
||||
|
@ -545,6 +632,22 @@ impl Codec for ServerKeyExchangePayload {
|
|||
}
|
||||
}
|
||||
|
||||
impl ServerKeyExchangePayload {
|
||||
pub fn unwrap_given_kxa(&self, kxa: &KeyExchangeAlgorithm) -> Option<ServerKeyExchangePayload> {
|
||||
if let ServerKeyExchangePayload::Unknown(ref unk) = *self {
|
||||
let mut rd = Reader::init(&unk.body);
|
||||
|
||||
return match *kxa {
|
||||
KeyExchangeAlgorithm::ECDHE_ECDSA | KeyExchangeAlgorithm::ECDHE_RSA =>
|
||||
ECDHEServerKeyExchange::read(&mut rd).and_then(|x| Some(ServerKeyExchangePayload::ECDHE(x))),
|
||||
_ => None
|
||||
};
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum HandshakePayload {
|
||||
HelloRequest,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
/* The single place where we generate random material
|
||||
* for our own use. These functions never fail,
|
||||
* they panic on error. */
|
||||
|
||||
extern crate ring;
|
||||
use self::ring::rand::SecureRandom;
|
||||
|
||||
/* Fill the whole slice with random material. */
|
||||
pub fn fill_random(bytes: &mut [u8]) {
|
||||
ring::rand::SystemRandom::new()
|
||||
.fill(bytes)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
/* Make the vec v contain sz random bytes. */
|
||||
pub fn fill_random_vec(v: &mut Vec<u8>, sz: usize) {
|
||||
v.resize(sz, 0u8);
|
||||
fill_random(v);
|
||||
}
|
|
@ -8,15 +8,13 @@ use msgs::deframer::MessageDeframer;
|
|||
use msgs::message::Message;
|
||||
use server_hs;
|
||||
use handshake::HandshakeError;
|
||||
use rand;
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
extern crate rand;
|
||||
use self::rand::Rng;
|
||||
|
||||
pub trait StoresSessions {
|
||||
/* Generate a session ID. */
|
||||
fn generate(&self) -> SessionID;
|
||||
|
@ -136,9 +134,7 @@ impl ServerHandshakeData {
|
|||
}
|
||||
|
||||
pub fn generate_server_random(&mut self) {
|
||||
let mut rng = rand::thread_rng();
|
||||
self.server_random.resize(32, 0);
|
||||
rng.fill_bytes(&mut self.server_random);
|
||||
rand::fill_random_vec(&mut self.server_random, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,28 @@
|
|||
use msgs::enums::{CipherSuite};
|
||||
use msgs::enums::{CipherSuite, HashAlgorithm};
|
||||
use msgs::handshake::KeyExchangeAlgorithm;
|
||||
use msgs::handshake::CertificatePayload;
|
||||
|
||||
extern crate ring;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BulkAlgorithm {
|
||||
AES_128_GCM,
|
||||
AES_256_GCM
|
||||
}
|
||||
|
||||
/* This contains the data we need to keep for a connection
|
||||
* for a particular kind of KX. */
|
||||
pub enum KeyExchangeData {
|
||||
ECDHE(ring::agreement::EphemeralKeyPair),
|
||||
Invalid
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SupportedCipherSuite {
|
||||
pub suite: CipherSuite,
|
||||
pub kx: KeyExchangeAlgorithm,
|
||||
pub bulk: BulkAlgorithm,
|
||||
pub hash: HashAlgorithm
|
||||
}
|
||||
|
||||
impl PartialEq for SupportedCipherSuite {
|
||||
|
@ -12,14 +31,26 @@ impl PartialEq for SupportedCipherSuite {
|
|||
}
|
||||
}
|
||||
|
||||
impl SupportedCipherSuite {
|
||||
pub fn init_kx(&self) -> KeyExchangeData {
|
||||
KeyExchangeData::Invalid
|
||||
}
|
||||
}
|
||||
|
||||
pub static TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: SupportedCipherSuite =
|
||||
SupportedCipherSuite {
|
||||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
|
||||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
||||
kx: KeyExchangeAlgorithm::ECDHE_RSA,
|
||||
bulk: BulkAlgorithm::AES_128_GCM,
|
||||
hash: HashAlgorithm::SHA256
|
||||
};
|
||||
|
||||
pub static TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: SupportedCipherSuite =
|
||||
SupportedCipherSuite {
|
||||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
suite: CipherSuite::TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
||||
kx: KeyExchangeAlgorithm::ECDHE_RSA,
|
||||
bulk: BulkAlgorithm::AES_256_GCM,
|
||||
hash: HashAlgorithm::SHA384
|
||||
};
|
||||
|
||||
pub static DEFAULT_CIPHERSUITES: [&'static SupportedCipherSuite; 2] = [
|
||||
|
|
Loading…
Reference in New Issue