1 #[cfg(test)] 2 mod handshake_cache_test; 3 4 use crate::cipher_suite::*; 5 use crate::handshake::*; 6 7 use std::collections::HashMap; 8 use std::io::BufReader; 9 use std::sync::Arc; 10 use tokio::sync::Mutex; 11 12 use sha2::{Digest, Sha256}; 13 14 #[derive(Clone, Debug)] 15 pub(crate) struct HandshakeCacheItem { 16 typ: HandshakeType, 17 is_client: bool, 18 epoch: u16, 19 message_sequence: u16, 20 data: Vec<u8>, 21 } 22 23 #[derive(Copy, Clone, Debug)] 24 pub(crate) struct HandshakeCachePullRule { 25 pub(crate) typ: HandshakeType, 26 pub(crate) epoch: u16, 27 pub(crate) is_client: bool, 28 pub(crate) optional: bool, 29 } 30 31 #[derive(Clone)] 32 pub(crate) struct HandshakeCache { 33 cache: Arc<Mutex<Vec<HandshakeCacheItem>>>, 34 } 35 36 impl HandshakeCache { new() -> Self37 pub(crate) fn new() -> Self { 38 HandshakeCache { 39 cache: Arc::new(Mutex::new(vec![])), 40 } 41 } 42 push( &mut self, data: Vec<u8>, epoch: u16, message_sequence: u16, typ: HandshakeType, is_client: bool, ) -> bool43 pub(crate) async fn push( 44 &mut self, 45 data: Vec<u8>, 46 epoch: u16, 47 message_sequence: u16, 48 typ: HandshakeType, 49 is_client: bool, 50 ) -> bool { 51 let mut cache = self.cache.lock().await; 52 53 for i in &*cache { 54 if i.message_sequence == message_sequence && i.is_client == is_client { 55 return false; 56 } 57 } 58 59 cache.push(HandshakeCacheItem { 60 typ, 61 is_client, 62 epoch, 63 message_sequence, 64 data, 65 }); 66 67 true 68 } 69 70 // returns a list handshakes that match the requested rules 71 // the list will contain null entries for rules that can't be satisfied 72 // multiple entries may match a rule, but only the last match is returned (ie ClientHello with cookies) pull(&self, rules: &[HandshakeCachePullRule]) -> Vec<HandshakeCacheItem>73 pub(crate) async fn pull(&self, rules: &[HandshakeCachePullRule]) -> Vec<HandshakeCacheItem> { 74 let cache = self.cache.lock().await; 75 76 let mut out = vec![]; 77 for r in rules { 78 let mut item: Option<HandshakeCacheItem> = None; 79 for c in &*cache { 80 if c.typ == r.typ && c.is_client == r.is_client && c.epoch == r.epoch { 81 if let Some(x) = &item { 82 if x.message_sequence < c.message_sequence { 83 item = Some(c.clone()); 84 } 85 } else { 86 item = Some(c.clone()); 87 } 88 } 89 } 90 91 if let Some(c) = item { 92 out.push(c); 93 } 94 } 95 96 out 97 } 98 99 // full_pull_map pulls all handshakes between rules[0] to rules[len(rules)-1] as map. full_pull_map( &self, start_seq: isize, rules: &[HandshakeCachePullRule], ) -> Result<(isize, HashMap<HandshakeType, HandshakeMessage>)>100 pub(crate) async fn full_pull_map( 101 &self, 102 start_seq: isize, 103 rules: &[HandshakeCachePullRule], 104 ) -> Result<(isize, HashMap<HandshakeType, HandshakeMessage>)> { 105 let cache = self.cache.lock().await; 106 107 let mut ci = HashMap::new(); 108 for r in rules { 109 let mut item: Option<HandshakeCacheItem> = None; 110 for c in &*cache { 111 if c.typ == r.typ && c.is_client == r.is_client && c.epoch == r.epoch { 112 if let Some(x) = &item { 113 if x.message_sequence < c.message_sequence { 114 item = Some(c.clone()); 115 } 116 } else { 117 item = Some(c.clone()); 118 } 119 } 120 } 121 if !r.optional && item.is_none() { 122 // Missing mandatory message. 123 return Err(Error::Other("Missing mandatory message".to_owned())); 124 } 125 126 if let Some(c) = item { 127 ci.insert(r.typ, c); 128 } 129 } 130 131 let mut out = HashMap::new(); 132 let mut seq = start_seq; 133 for r in rules { 134 let t = r.typ; 135 if let Some(i) = ci.get(&t) { 136 let mut reader = BufReader::new(i.data.as_slice()); 137 let raw_handshake = Handshake::unmarshal(&mut reader)?; 138 if seq as u16 != raw_handshake.handshake_header.message_sequence { 139 // There is a gap. Some messages are not arrived. 140 return Err(Error::Other( 141 "There is a gap. Some messages are not arrived.".to_owned(), 142 )); 143 } 144 seq += 1; 145 out.insert(t, raw_handshake.handshake_message); 146 } 147 } 148 149 Ok((seq, out)) 150 } 151 152 // pull_and_merge calls pull and then merges the results, ignoring any null entries pull_and_merge(&self, rules: &[HandshakeCachePullRule]) -> Vec<u8>153 pub(crate) async fn pull_and_merge(&self, rules: &[HandshakeCachePullRule]) -> Vec<u8> { 154 let mut merged = vec![]; 155 156 for p in &self.pull(rules).await { 157 merged.extend_from_slice(&p.data); 158 } 159 160 merged 161 } 162 163 // session_hash returns the session hash for Extended Master Secret support 164 // https://tools.ietf.org/html/draft-ietf-tls-session-hash-06#section-4 session_hash( &self, hf: CipherSuiteHash, epoch: u16, additional: &[u8], ) -> Result<Vec<u8>>165 pub(crate) async fn session_hash( 166 &self, 167 hf: CipherSuiteHash, 168 epoch: u16, 169 additional: &[u8], 170 ) -> Result<Vec<u8>> { 171 let mut merged = vec![]; 172 173 // Order defined by https://tools.ietf.org/html/rfc5246#section-7.3 174 let handshake_buffer = self 175 .pull(&[ 176 HandshakeCachePullRule { 177 typ: HandshakeType::ClientHello, 178 epoch, 179 is_client: true, 180 optional: false, 181 }, 182 HandshakeCachePullRule { 183 typ: HandshakeType::ServerHello, 184 epoch, 185 is_client: false, 186 optional: false, 187 }, 188 HandshakeCachePullRule { 189 typ: HandshakeType::Certificate, 190 epoch, 191 is_client: false, 192 optional: false, 193 }, 194 HandshakeCachePullRule { 195 typ: HandshakeType::ServerKeyExchange, 196 epoch, 197 is_client: false, 198 optional: false, 199 }, 200 HandshakeCachePullRule { 201 typ: HandshakeType::CertificateRequest, 202 epoch, 203 is_client: false, 204 optional: false, 205 }, 206 HandshakeCachePullRule { 207 typ: HandshakeType::ServerHelloDone, 208 epoch, 209 is_client: false, 210 optional: false, 211 }, 212 HandshakeCachePullRule { 213 typ: HandshakeType::Certificate, 214 epoch, 215 is_client: true, 216 optional: false, 217 }, 218 HandshakeCachePullRule { 219 typ: HandshakeType::ClientKeyExchange, 220 epoch, 221 is_client: true, 222 optional: false, 223 }, 224 ]) 225 .await; 226 227 for p in &handshake_buffer { 228 merged.extend_from_slice(&p.data); 229 } 230 231 merged.extend_from_slice(additional); 232 233 let mut hasher = match hf { 234 CipherSuiteHash::Sha256 => Sha256::new(), 235 }; 236 hasher.update(&merged); 237 let result = hasher.finalize(); 238 239 Ok(result.as_slice().to_vec()) 240 } 241 } 242