handshake.rs 6.6 KB

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