Skip to content

Instantly share code, notes, and snippets.

@jonasschneider
Created December 5, 2015 21:33
extern crate tls;
extern crate byteorder;
extern crate openssl;
extern crate crypto;
use std::fs::File;
use std::io::{Read,Write,Cursor};
use std::net::TcpListener;
use tls::record::{TLSCiphertext,TLSPlaintext,ConnectionState};
use tls::handshake;
use byteorder::{WriteBytesExt,BigEndian};
use openssl::crypto::pkey::{PKey,EncryptionPadding};
const TLS_RSA_WITH_AES_128_CBC_SHA: u16 = 0x002f;
#[derive(Debug)]
struct AlertType;
#[derive(Debug)]
enum Subprotocol {
Handshake(handshake::Message),
Alert(AlertType),
ChangeCipherSpec,
ApplicationData,
}
trait ProtocolChooser {
fn subprotocol(self: Self) -> Option<Subprotocol>;
}
impl ProtocolChooser for TLSPlaintext {
fn subprotocol(self: TLSPlaintext) -> Option<Subprotocol> {
match self.content_type {
22 => match handshake::Message::parse(self.body) {
Some(x) => Some(Subprotocol::Handshake(x)),
_ => None,
},
_ => None,
}
}
}
use openssl::crypto::hash::Type;
//use openssl::crypto::hmac::hmac;
use crypto::hmac::Hmac;
use crypto::sha2::Sha256;
use crypto::mac::Mac;
fn prf(secret: &[u8], seed: &[u8], dest: &mut [u8]) {
let mut hmac = Hmac::new(Sha256::new(), secret);
let mut n: usize = 0;
let mut a = [0 as u8; 32];
hmac.input(seed);
hmac.raw_result(&mut a);
hmac.reset();
while n < dest.len() {
hmac.input(&a);
hmac.input(seed);
let mut buf = [0 as u8; 32];
hmac.raw_result(&mut buf);
hmac.reset();
let mut i=0;
while i < 32 && n+i < dest.len() {
dest[n+i] = buf[i];
i+=1;
}
n+=32;
hmac.input(&a);
hmac.raw_result(&mut a);
hmac.reset();
}
}
fn main() {
let listener = TcpListener::bind("0.0.0.0:9123").unwrap();
println!("listening started, ready to accept");
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let mut bytes = Vec::<u8>::with_capacity(1000);
unsafe {
bytes.set_len(1000);
}
let n = stream.read(&mut bytes[..]).unwrap();
bytes.split_off(n);
println!("read {}: {:?}",n,bytes);
let ct = TLSCiphertext::from_wire_bytes(bytes);
let pt = ct.decipher(ConnectionState::initial());
println!("plaintext packet: {:?}",pt);
let client_random;
match pt.subprotocol() {
Some(Subprotocol::Handshake(handshake::Message::TypeClientHello(helo))) =>
{
let mut found = false;
for suite in helo.offered_suites {
if suite == TLS_RSA_WITH_AES_128_CBC_SHA {
found = true;
break
}
}
if !found {
panic!("client didn't offer TLS_RSA_WITH_AES_128_CBC_SHA");
}
client_random = helo.client_random;
},
_ =>
panic!("client didn't send a valid ClientHello"),
}
let mut repbuf = [0 as u8; 1000];
let server_random = [1 as u8; 32];
let n;
{
let mut replyc = Cursor::new(&mut repbuf[..]);
replyc.write_u8(22).unwrap();
replyc.write_u8(3).unwrap();
replyc.write_u8(3).unwrap();
replyc.write_u16::<BigEndian>(42).unwrap(); // len
//lenpos = replyc.position();
replyc.write_u8(2).unwrap(); // serverhello
replyc.write_u8(0).unwrap(); // high length
replyc.write_u16::<BigEndian>(38).unwrap(); // inner length
println!("start of inner at {}", replyc.position());
replyc.write_u8(3).unwrap(); // ver
replyc.write_u8(3).unwrap(); // ver
for i in 0..32 {
replyc.write_u8(1).unwrap(); // our rand
}
replyc.write_u8(0).unwrap(); // sessid length
//replyc.write_u8(32).unwrap(); // sessid
replyc.write_u16::<BigEndian>(TLS_RSA_WITH_AES_128_CBC_SHA).unwrap();
replyc.write_u8(0).unwrap(); // chosen compression
//replyc.write_u16::<BigEndian>(0).unwrap(); // extension length
// for i in 0..15 {
// replyc.write_u8(0).unwrap(); // dummy ext
// }
n = replyc.position();
}
println!("constructed {} bytes",n);
{
let to_send = &repbuf[0..(n as usize)];
println!("sending: {}, {:?}",to_send.len(),to_send);
let sent = stream.write(to_send).unwrap();
println!("sent {}",sent);
}
let mut certbuf = [0 as u8; 4096];
let mut f = File::open("keys/server.crt.der").unwrap();
let certlen = f.read(&mut certbuf).unwrap();
let cert: &[u8] = &certbuf[0..certlen];
let certlen_u16 = certlen as u16;
println!("cert is {} bytes long", certlen);
let n2;
{
let mut replyc = Cursor::new(&mut repbuf[..]);
replyc.write_u8(22).unwrap();
replyc.write_u8(3).unwrap();
replyc.write_u8(3).unwrap();
replyc.write_u16::<BigEndian>(certlen_u16+3+3+4).unwrap(); // outer len
// certificate message
replyc.write_u8(11).unwrap(); // certificate
replyc.write_u8(0).unwrap(); // high length
replyc.write_u16::<BigEndian>(certlen_u16+3+3).unwrap(); // inner length
// certificate_list
replyc.write_u8(0).unwrap();
replyc.write_u16::<BigEndian>(certlen_u16+3).unwrap();
replyc.write_u8(0).unwrap();
replyc.write_u16::<BigEndian>(certlen_u16).unwrap();
replyc.write(cert);
n2 = replyc.position();
}
{
let to_send = &repbuf[0..(n2 as usize)];
println!("sending: {}, {:?}",to_send.len(),to_send);
let sent = stream.write(to_send).unwrap();
println!("sent {}",sent);
}
let n3;
{
let mut replyc = Cursor::new(&mut repbuf[..]);
replyc.write_u8(22).unwrap();
replyc.write_u8(3).unwrap();
replyc.write_u8(3).unwrap();
replyc.write_u16::<BigEndian>(4).unwrap(); // outer len
replyc.write_u8(14).unwrap(); // server_hello_done
replyc.write_u8(0).unwrap(); // high length
replyc.write_u16::<BigEndian>(0).unwrap(); // inner length
n3 = replyc.position();
}
{
let to_send = &repbuf[0..(n3 as usize)];
println!("sending: {}, {:?}",to_send.len(),to_send);
let sent = stream.write(to_send).unwrap();
println!("sent {}",sent);
}
stream.write(b"Hello World\r\n").unwrap();
let mut f = File::open("keys/server.key").unwrap();
let pk = openssl::crypto::pkey::PKey::private_key_from_pem(&mut f).unwrap();
println!("pk: {}, {:?}", pk.size(), pk.max_data());
let mut pmsbuf = [0 as u8; 4096];
let clientkexlen = stream.read(&mut pmsbuf[..]).unwrap();
println!("kexlen: {}, {:?}", clientkexlen, &pmsbuf[0..clientkexlen]);
let premastersecret = pk.private_decrypt_with_padding(&pmsbuf[11..(11+128)], EncryptionPadding::PKCS1v15);
assert!(48 == premastersecret.len());
println!("client random: {:?}", client_random);
println!("server random: {:?}", server_random);
let mut master_secret: [u8; 48] = [0 as u8; 48];
let mut seed = Vec::new();
seed.extend(b"master secret");
seed.extend(&client_random);
seed.extend(&server_random);
//assert!(64 == seed.len());
println!("{:?}", seed);
prf(&premastersecret[..], &seed[..], &mut master_secret);
for b in master_secret.into_iter() {
print!("{:02X}", b);
}
println!("");
// let strs: String = master_secret.into_iter()
// .map(|b| format!("{:02X}", b))
// .collect().connect("");
// println!("master key: {}", strs);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment