1 use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
2 use futures::{Async, Future, Poll};
3 use hmac::{Hmac, Mac};
4 use protobuf::{self, Message};
5 use rand::thread_rng;
6 use sha1::Sha1;
7 use std::io::{self, Read};
8 use std::marker::PhantomData;
9 use tokio_codec::{Decoder, Framed};
10 use tokio_io::io::{read_exact, write_all, ReadExact, Window, WriteAll};
11 use tokio_io::{AsyncRead, AsyncWrite};
12
13 use super::codec::APCodec;
14 use crate::diffie_hellman::DHLocalKeys;
15 use crate::protocol;
16 use crate::protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext};
17 use crate::util;
18
19 pub struct Handshake<T> {
20 keys: DHLocalKeys,
21 state: HandshakeState<T>,
22 }
23
24 enum HandshakeState<T> {
25 ClientHello(WriteAll<T, Vec<u8>>),
26 APResponse(RecvPacket<T, APResponseMessage>),
27 ClientResponse(Option<APCodec>, WriteAll<T, Vec<u8>>),
28 }
29
handshake<T: AsyncRead + AsyncWrite>(connection: T) -> Handshake<T>30 pub fn handshake<T: AsyncRead + AsyncWrite>(connection: T) -> Handshake<T> {
31 let local_keys = DHLocalKeys::random(&mut thread_rng());
32 let client_hello = client_hello(connection, local_keys.public_key());
33
34 Handshake {
35 keys: local_keys,
36 state: HandshakeState::ClientHello(client_hello),
37 }
38 }
39
40 impl<T: AsyncRead + AsyncWrite> Future for Handshake<T> {
41 type Item = Framed<T, APCodec>;
42 type Error = io::Error;
43
poll(&mut self) -> Poll<Self::Item, io::Error>44 fn poll(&mut self) -> Poll<Self::Item, io::Error> {
45 use self::HandshakeState::*;
46 loop {
47 self.state = match self.state {
48 ClientHello(ref mut write) => {
49 let (connection, accumulator) = try_ready!(write.poll());
50
51 let read = recv_packet(connection, accumulator);
52 APResponse(read)
53 }
54
55 APResponse(ref mut read) => {
56 let (connection, message, accumulator) = try_ready!(read.poll());
57 let remote_key = message
58 .get_challenge()
59 .get_login_crypto_challenge()
60 .get_diffie_hellman()
61 .get_gs()
62 .to_owned();
63
64 let shared_secret = self.keys.shared_secret(&remote_key);
65 let (challenge, send_key, recv_key) =
66 compute_keys(&shared_secret, &accumulator);
67 let codec = APCodec::new(&send_key, &recv_key);
68
69 let write = client_response(connection, challenge);
70 ClientResponse(Some(codec), write)
71 }
72
73 ClientResponse(ref mut codec, ref mut write) => {
74 let (connection, _) = try_ready!(write.poll());
75 let codec = codec.take().unwrap();
76 let framed = codec.framed(connection);
77 return Ok(Async::Ready(framed));
78 }
79 }
80 }
81 }
82 }
83
client_hello<T: AsyncWrite>(connection: T, gc: Vec<u8>) -> WriteAll<T, Vec<u8>>84 fn client_hello<T: AsyncWrite>(connection: T, gc: Vec<u8>) -> WriteAll<T, Vec<u8>> {
85 let mut packet = ClientHello::new();
86 packet
87 .mut_build_info()
88 .set_product(protocol::keyexchange::Product::PRODUCT_PARTNER);
89 packet
90 .mut_build_info()
91 .set_platform(protocol::keyexchange::Platform::PLATFORM_LINUX_X86);
92 packet.mut_build_info().set_version(109800078);
93 packet
94 .mut_cryptosuites_supported()
95 .push(protocol::keyexchange::Cryptosuite::CRYPTO_SUITE_SHANNON);
96 packet
97 .mut_login_crypto_hello()
98 .mut_diffie_hellman()
99 .set_gc(gc);
100 packet
101 .mut_login_crypto_hello()
102 .mut_diffie_hellman()
103 .set_server_keys_known(1);
104 packet.set_client_nonce(util::rand_vec(&mut thread_rng(), 0x10));
105 packet.set_padding(vec![0x1e]);
106
107 let mut buffer = vec![0, 4];
108 let size = 2 + 4 + packet.compute_size();
109 buffer.write_u32::<BigEndian>(size).unwrap();
110 packet.write_to_vec(&mut buffer).unwrap();
111
112 write_all(connection, buffer)
113 }
114
client_response<T: AsyncWrite>(connection: T, challenge: Vec<u8>) -> WriteAll<T, Vec<u8>>115 fn client_response<T: AsyncWrite>(connection: T, challenge: Vec<u8>) -> WriteAll<T, Vec<u8>> {
116 let mut packet = ClientResponsePlaintext::new();
117 packet
118 .mut_login_crypto_response()
119 .mut_diffie_hellman()
120 .set_hmac(challenge);
121 packet.mut_pow_response();
122 packet.mut_crypto_response();
123
124 let mut buffer = vec![];
125 let size = 4 + packet.compute_size();
126 buffer.write_u32::<BigEndian>(size).unwrap();
127 packet.write_to_vec(&mut buffer).unwrap();
128
129 write_all(connection, buffer)
130 }
131
132 enum RecvPacket<T, M: Message> {
133 Header(ReadExact<T, Window<Vec<u8>>>, PhantomData<M>),
134 Body(ReadExact<T, Window<Vec<u8>>>, PhantomData<M>),
135 }
136
recv_packet<T: AsyncRead, M>(connection: T, acc: Vec<u8>) -> RecvPacket<T, M> where T: Read, M: Message,137 fn recv_packet<T: AsyncRead, M>(connection: T, acc: Vec<u8>) -> RecvPacket<T, M>
138 where
139 T: Read,
140 M: Message,
141 {
142 RecvPacket::Header(read_into_accumulator(connection, 4, acc), PhantomData)
143 }
144
145 impl<T: AsyncRead, M> Future for RecvPacket<T, M>
146 where
147 T: Read,
148 M: Message,
149 {
150 type Item = (T, M, Vec<u8>);
151 type Error = io::Error;
152
poll(&mut self) -> Poll<Self::Item, io::Error>153 fn poll(&mut self) -> Poll<Self::Item, io::Error> {
154 use self::RecvPacket::*;
155 loop {
156 *self = match *self {
157 Header(ref mut read, _) => {
158 let (connection, header) = try_ready!(read.poll());
159 let size = BigEndian::read_u32(header.as_ref()) as usize;
160
161 let acc = header.into_inner();
162 let read = read_into_accumulator(connection, size - 4, acc);
163 RecvPacket::Body(read, PhantomData)
164 }
165
166 Body(ref mut read, _) => {
167 let (connection, data) = try_ready!(read.poll());
168 let message = protobuf::parse_from_bytes(data.as_ref()).unwrap();
169
170 let acc = data.into_inner();
171 return Ok(Async::Ready((connection, message, acc)));
172 }
173 }
174 }
175 }
176 }
177
read_into_accumulator<T: AsyncRead>( connection: T, size: usize, mut acc: Vec<u8>, ) -> ReadExact<T, Window<Vec<u8>>>178 fn read_into_accumulator<T: AsyncRead>(
179 connection: T,
180 size: usize,
181 mut acc: Vec<u8>,
182 ) -> ReadExact<T, Window<Vec<u8>>> {
183 let offset = acc.len();
184 acc.resize(offset + size, 0);
185
186 let mut window = Window::new(acc);
187 window.set_start(offset);
188
189 read_exact(connection, window)
190 }
191
compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec<u8>, Vec<u8>, Vec<u8>)192 fn compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
193 type HmacSha1 = Hmac<Sha1>;
194
195 let mut data = Vec::with_capacity(0x64);
196 for i in 1..6 {
197 let mut mac = HmacSha1::new_varkey(&shared_secret).expect("HMAC can take key of any size");
198 mac.input(packets);
199 mac.input(&[i]);
200 data.extend_from_slice(&mac.result().code());
201 }
202
203 let mut mac = HmacSha1::new_varkey(&data[..0x14]).expect("HMAC can take key of any size");
204 mac.input(packets);
205
206 (
207 mac.result().code().to_vec(),
208 data[0x14..0x34].to_vec(),
209 data[0x34..0x54].to_vec(),
210 )
211 }
212