handshake.rs 6.6 KB

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