brass_aphid_wire_decryption/decryption/
stream_decrypter.rs1use crate::decryption::{
2 key_manager::KeyManager, tls_stream::TlsStream, transcript::Transcript, Mode,
3};
4use brass_aphid_wire_messages::{
5 iana::{self, Protocol},
6 protocol::{
7 content_value::{ContentValue, HandshakeMessageValue},
8 ServerHelloConfusionMode,
9 },
10};
11use std::{
12 path::PathBuf,
13 sync::{Arc, Mutex},
14};
15
16#[derive(Debug, Default, Clone)]
20pub struct ConversationState {
21 pub client_random: Option<Vec<u8>>,
22 pub selected_protocol: Option<Protocol>,
23 pub selected_cipher: Option<iana::Cipher>,
24}
25
26#[derive(Debug)]
27pub struct StreamDecrypter {
28 pub state: ConversationState,
29 key_manager: KeyManager,
34 pub transcript: Arc<Mutex<Vec<(Mode, ContentValue)>>>,
35 pub client_stream: TlsStream,
36 pub server_stream: TlsStream,
37}
38
39impl StreamDecrypter {
40 pub fn new(key_manager: KeyManager) -> Self {
41 Self {
42 state: ConversationState::default(),
43 key_manager,
44 transcript: Default::default(),
45 client_stream: TlsStream::new(Mode::Client),
46 server_stream: TlsStream::new(Mode::Server),
47 }
48 }
49
50 pub fn record_tx(&mut self, data: &[u8], sender: Mode) {
56 match sender {
57 Mode::Client => self.client_stream.feed_bytes(data),
58 Mode::Server => self.server_stream.feed_bytes(data),
59 };
60 }
61
62 pub fn transcript(&self) -> Transcript {
63 Transcript {
64 record_transcript: Default::default(),
65 content_transcript: Mutex::new(self.transcript.lock().unwrap().clone()),
66 }
67 }
68
69 pub fn dump_transcript(&self, file: &PathBuf) {
70 let transcript = format!("{:#?}", self.transcript);
71 std::fs::write(file, transcript).unwrap();
72 }
73
74 pub fn assemble_records(&mut self, mode: Mode) -> std::io::Result<()> {
75 Ok(())
82 }
83
84 pub fn decrypt_records(&mut self, mode: Mode) -> std::io::Result<()> {
86 let content = match mode {
87 Mode::Client => self
88 .client_stream
89 .digest_bytes(&mut self.state, &self.key_manager),
90 Mode::Server => self
91 .server_stream
92 .digest_bytes(&mut self.state, &self.key_manager),
93 }?;
94
95 let hello_retry = content.iter().any(|content| {
100 matches!(
101 content,
102 ContentValue::Handshake(HandshakeMessageValue::ServerHelloConfusion(
103 ServerHelloConfusionMode::HelloRetryRequest(_)
104 ))
105 )
106 });
107
108 if hello_retry {
109 debug_assert_eq!(mode, Mode::Server);
111 self.client_stream.suppress_next_key_state();
112 }
113
114 self.transcript
115 .lock()
116 .unwrap()
117 .extend(content.into_iter().map(|content| (mode, content)));
118 Ok(())
119 }
120}