loco_protocol/secure/
client.rs1pub use rsa;
8
9use alloc::{boxed::Box, collections::VecDeque, vec::Vec};
10use core::mem;
11
12use aes::cipher::{AsyncStreamCipher, Key, KeyIvInit};
13use arrayvec::ArrayVec;
14use rand::thread_rng;
15use rsa::{Oaep, RsaPublicKey};
16use serde::{Deserialize, Serialize};
17use sha1::Sha1;
18
19use super::SecurePacket;
20
21type Aes128CfbEnc = cfb_mode::Encryptor<aes::Aes128>;
22type Aes128CfbDec = cfb_mode::Decryptor<aes::Aes128>;
23
24#[derive(Debug)]
25pub struct LocoClientSecureLayer {
27 key: Key<aes::Aes128>,
28
29 read_state: ReadState,
30
31 encrypt_buffer: Vec<u8>,
32
33 pub read_buffer: VecDeque<u8>,
35
36 pub write_buffer: VecDeque<u8>,
38}
39
40impl LocoClientSecureLayer {
41 pub fn new(encrypt_key: [u8; 16]) -> Self {
43 Self {
44 key: encrypt_key.into(),
45
46 read_state: ReadState::Pending,
47
48 encrypt_buffer: Vec::new(),
49
50 read_buffer: VecDeque::new(),
51 write_buffer: VecDeque::new(),
52 }
53 }
54
55 pub const fn read_state(&self) -> &ReadState {
56 &self.read_state
57 }
58
59 pub fn handshake(&mut self, key: &RsaPublicKey) {
61 #[derive(Serialize)]
62 struct RawHandshakeHeader {
63 encrypted_key_size: u32,
64 key_type: u32,
65 encrypt_type: u32,
66 }
67
68 let encrypted_key = key
69 .encrypt(
70 &mut thread_rng(),
71 Oaep::new_with_mgf_hash::<Sha1, Sha1>(),
72 self.key.as_slice(),
73 )
74 .unwrap();
75
76 bincode::serialize_into(
77 &mut self.write_buffer,
78 &RawHandshakeHeader {
79 encrypted_key_size: encrypted_key.len() as u32,
80 key_type: 15, encrypt_type: 2, },
83 )
84 .unwrap();
85
86 self.write_buffer.extend(encrypted_key);
87 }
88
89 pub fn read(&mut self) -> Option<SecurePacket<Box<[u8]>>> {
91 loop {
92 match mem::replace(&mut self.read_state, ReadState::Corrupted) {
93 ReadState::Pending => {
94 if self.read_buffer.len() < 20 {
95 self.read_state = ReadState::Pending;
96 return None;
97 }
98
99 let raw_header = {
100 let buf = self.read_buffer.drain(..20).collect::<ArrayVec<u8, 20>>();
101
102 bincode::deserialize::<RawHeader>(&buf).unwrap()
103 };
104
105 self.read_state = ReadState::Header(raw_header);
106 }
107
108 ReadState::Header(raw_header) => {
109 let size = raw_header.size as usize - 16;
110
111 if self.read_buffer.len() < size {
112 self.read_state = ReadState::Header(raw_header);
113 return None;
114 }
115
116 let mut data = self.read_buffer.drain(..size).collect::<Box<[u8]>>();
117 Aes128CfbDec::new(&self.key, &raw_header.iv.into()).decrypt(&mut data);
118
119 self.read_state = ReadState::Pending;
120 return Some(SecurePacket {
121 iv: raw_header.iv,
122 data,
123 });
124 }
125
126 ReadState::Corrupted => unreachable!(),
127 }
128 }
129 }
130
131 pub fn send(&mut self, packet: SecurePacket<impl AsRef<[u8]>>) {
133 let encrypted_data = {
134 let data = packet.data.as_ref();
135
136 self.encrypt_buffer.extend(data);
137 Aes128CfbEnc::new(&self.key, &packet.iv.into()).encrypt(&mut self.encrypt_buffer);
138
139 &mut self.encrypt_buffer
140 };
141
142 bincode::serialize_into(
143 &mut self.write_buffer,
144 &RawHeader {
145 size: 16 + encrypted_data.len() as u32,
146 iv: packet.iv,
147 },
148 )
149 .unwrap();
150
151 self.write_buffer.extend(encrypted_data.drain(..));
152 }
153}
154
155#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
156pub struct RawHeader {
157 pub size: u32,
159
160 pub iv: [u8; 16],
162}
163
164#[derive(Debug, Clone, PartialEq)]
165pub enum ReadState {
166 Pending,
168
169 Header(RawHeader),
171
172 Corrupted,
174}