1 use byteorder::{BigEndian, ByteOrder, WriteBytesExt};
2 use hmac::{Hmac, Mac, NewMac};
3 use protobuf::{self, Message};
4 use rand::{thread_rng, RngCore};
5 use sha1::Sha1;
6 use std::io;
7 use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
8 use tokio_util::codec::{Decoder, Framed};
9 
10 use super::codec::ApCodec;
11 use crate::diffie_hellman::DhLocalKeys;
12 use crate::protocol;
13 use crate::protocol::keyexchange::{APResponseMessage, ClientHello, ClientResponsePlaintext};
14 
handshake<T: AsyncRead + AsyncWrite + Unpin>( mut connection: T, ) -> io::Result<Framed<T, ApCodec>>15 pub async fn handshake<T: AsyncRead + AsyncWrite + Unpin>(
16     mut connection: T,
17 ) -> io::Result<Framed<T, ApCodec>> {
18     let local_keys = DhLocalKeys::random(&mut thread_rng());
19     let gc = local_keys.public_key();
20     let mut accumulator = client_hello(&mut connection, gc).await?;
21     let message: APResponseMessage = recv_packet(&mut connection, &mut accumulator).await?;
22     let remote_key = message
23         .get_challenge()
24         .get_login_crypto_challenge()
25         .get_diffie_hellman()
26         .get_gs()
27         .to_owned();
28 
29     let shared_secret = local_keys.shared_secret(&remote_key);
30     let (challenge, send_key, recv_key) = compute_keys(&shared_secret, &accumulator);
31     let codec = ApCodec::new(&send_key, &recv_key);
32 
33     client_response(&mut connection, challenge).await?;
34 
35     Ok(codec.framed(connection))
36 }
37 
client_hello<T>(connection: &mut T, gc: Vec<u8>) -> io::Result<Vec<u8>> where T: AsyncWrite + Unpin,38 async fn client_hello<T>(connection: &mut T, gc: Vec<u8>) -> io::Result<Vec<u8>>
39 where
40     T: AsyncWrite + Unpin,
41 {
42     let mut client_nonce = vec![0; 0x10];
43     thread_rng().fill_bytes(&mut client_nonce);
44 
45     let mut packet = ClientHello::new();
46     packet
47         .mut_build_info()
48         .set_product(protocol::keyexchange::Product::PRODUCT_PARTNER);
49     packet
50         .mut_build_info()
51         .set_platform(protocol::keyexchange::Platform::PLATFORM_LINUX_X86);
52     packet.mut_build_info().set_version(109800078);
53     packet
54         .mut_cryptosuites_supported()
55         .push(protocol::keyexchange::Cryptosuite::CRYPTO_SUITE_SHANNON);
56     packet
57         .mut_login_crypto_hello()
58         .mut_diffie_hellman()
59         .set_gc(gc);
60     packet
61         .mut_login_crypto_hello()
62         .mut_diffie_hellman()
63         .set_server_keys_known(1);
64     packet.set_client_nonce(client_nonce);
65     packet.set_padding(vec![0x1e]);
66 
67     let mut buffer = vec![0, 4];
68     let size = 2 + 4 + packet.compute_size();
69     <Vec<u8> as WriteBytesExt>::write_u32::<BigEndian>(&mut buffer, size).unwrap();
70     packet.write_to_vec(&mut buffer).unwrap();
71 
72     connection.write_all(&buffer[..]).await?;
73     Ok(buffer)
74 }
75 
client_response<T>(connection: &mut T, challenge: Vec<u8>) -> io::Result<()> where T: AsyncWrite + Unpin,76 async fn client_response<T>(connection: &mut T, challenge: Vec<u8>) -> io::Result<()>
77 where
78     T: AsyncWrite + Unpin,
79 {
80     let mut packet = ClientResponsePlaintext::new();
81     packet
82         .mut_login_crypto_response()
83         .mut_diffie_hellman()
84         .set_hmac(challenge);
85     packet.mut_pow_response();
86     packet.mut_crypto_response();
87 
88     let mut buffer = vec![];
89     let size = 4 + packet.compute_size();
90     <Vec<u8> as WriteBytesExt>::write_u32::<BigEndian>(&mut buffer, size).unwrap();
91     packet.write_to_vec(&mut buffer).unwrap();
92 
93     connection.write_all(&buffer[..]).await?;
94     Ok(())
95 }
96 
recv_packet<T, M>(connection: &mut T, acc: &mut Vec<u8>) -> io::Result<M> where T: AsyncRead + Unpin, M: Message,97 async fn recv_packet<T, M>(connection: &mut T, acc: &mut Vec<u8>) -> io::Result<M>
98 where
99     T: AsyncRead + Unpin,
100     M: Message,
101 {
102     let header = read_into_accumulator(connection, 4, acc).await?;
103     let size = BigEndian::read_u32(header) as usize;
104     let data = read_into_accumulator(connection, size - 4, acc).await?;
105     let message = M::parse_from_bytes(data).unwrap();
106     Ok(message)
107 }
108 
read_into_accumulator<'a, 'b, T: AsyncRead + Unpin>( connection: &'a mut T, size: usize, acc: &'b mut Vec<u8>, ) -> io::Result<&'b mut [u8]>109 async fn read_into_accumulator<'a, 'b, T: AsyncRead + Unpin>(
110     connection: &'a mut T,
111     size: usize,
112     acc: &'b mut Vec<u8>,
113 ) -> io::Result<&'b mut [u8]> {
114     let offset = acc.len();
115     acc.resize(offset + size, 0);
116 
117     connection.read_exact(&mut acc[offset..]).await?;
118     Ok(&mut acc[offset..])
119 }
120 
compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec<u8>, Vec<u8>, Vec<u8>)121 fn compute_keys(shared_secret: &[u8], packets: &[u8]) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
122     type HmacSha1 = Hmac<Sha1>;
123 
124     let mut data = Vec::with_capacity(0x64);
125     for i in 1..6 {
126         let mut mac =
127             HmacSha1::new_from_slice(shared_secret).expect("HMAC can take key of any size");
128         mac.update(packets);
129         mac.update(&[i]);
130         data.extend_from_slice(&mac.finalize().into_bytes());
131     }
132 
133     let mut mac = HmacSha1::new_from_slice(&data[..0x14]).expect("HMAC can take key of any size");
134     mac.update(packets);
135 
136     (
137         mac.finalize().into_bytes().to_vec(),
138         data[0x14..0x34].to_vec(),
139         data[0x34..0x54].to_vec(),
140     )
141 }
142