handshake.rs 6.5 KB

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