ytls_server/server_ctx/
s_application.rs1use crate::{CtxError, Rfc8446Error};
4use ytls_traits::CtxApplicationProcessor;
5use ytls_traits::ShutdownComplete;
6use ytls_traits::{TlsLeftIn, TlsLeftOut, TlsRight};
7
8use ytls_traits::CryptoConfig;
9use ytls_traits::SecretStore;
10
11use ytls_record::Content;
12use ytls_record::Record;
13use ytls_util::Nonce12;
14
15#[cfg(feature = "zeroize")]
16use zeroize::{Zeroize, ZeroizeOnDrop};
17
18#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
20pub struct ServerApplicationCtx<Crypto> {
21 application_server_key: [u8; 32],
23 application_client_key: [u8; 32],
24 #[cfg_attr(feature = "zeroize", zeroize(skip))]
25 application_server_iv: Nonce12,
26 #[cfg_attr(feature = "zeroize", zeroize(skip))]
27 application_client_iv: Nonce12,
28 _pt: core::marker::PhantomData<Crypto>,
29}
30
31impl<Crypto> ServerApplicationCtx<Crypto>
32where
33 Crypto: CryptoConfig,
34{
35 pub fn with_required<S: SecretStore>(_crypto: Crypto, s: &S) -> Self {
36 let mut application_server_key: [u8; 32] = [0; 32];
37 let mut application_client_key: [u8; 32] = [0; 32];
38 let mut application_server_iv_raw: [u8; 12] = [0; 12];
39 let mut application_client_iv_raw: [u8; 12] = [0; 12];
40
41 application_server_key.copy_from_slice(s.load_ap_server_key());
42 application_client_key.copy_from_slice(s.load_ap_client_key());
43 application_server_iv_raw.copy_from_slice(s.load_ap_server_iv());
44 application_client_iv_raw.copy_from_slice(s.load_ap_client_iv());
45
46 let application_server_iv = Nonce12::from_ks_iv(&application_server_iv_raw);
47 let application_client_iv = Nonce12::from_ks_iv(&application_client_iv_raw);
48
49 Self {
50 _pt: core::marker::PhantomData,
51 application_server_key,
52 application_client_key,
53 application_server_iv,
54 application_client_iv,
55 }
56 }
57}
58
59impl<Crypto> CtxApplicationProcessor for ServerApplicationCtx<Crypto>
60where
61 Crypto: CryptoConfig,
62{
63 type Error = CtxError;
64
65 fn spin_application<Li: TlsLeftIn, Lo: TlsLeftOut, R: TlsRight>(
66 &mut self,
67 li: &mut Li,
68 lo: &mut Lo,
69 right: &mut R,
70 ) -> Result<Option<ShutdownComplete>, Self::Error> {
71 let init_data = li.left_buf_in();
72 let init_len = init_data.len();
73 let mut data = init_data;
74
75 if init_len == 0 {
76 return Ok(None);
77 }
78
79 #[allow(unused_assignments)]
80 let mut consumed = 0;
81
82 loop {
83 let (rec, remaining) =
84 Record::parse_client_appdata(data).map_err(|e| CtxError::Record(e))?;
85
86 consumed = init_len - remaining.len();
87
88 if let Content::ApplicationData = rec.content() {
89 let key = self.application_client_key;
90 let nonce: [u8; 12] = match self.application_client_iv.use_and_incr() {
91 Some(cur) => cur,
92 None => return Err(CtxError::ExhaustedIv),
93 };
94
95 let cipher = Crypto::aead_chaha20poly1305(&key);
96 let full_payload = rec.as_bytes();
97 let full_payload_len = full_payload.len();
98 let mut tag: [u8; 16] = [0; 16];
99
100 let body_len = full_payload_len - 16;
101 let mut body: [u8; 8192] = [0; 8192];
102 body[0..body_len].copy_from_slice(&full_payload[0..body_len]);
103 tag.copy_from_slice(&full_payload[body_len..body_len + 16]);
104 let additional_data = rec.header_as_bytes();
105 use ytls_traits::CryptoChaCha20Poly1305Processor;
106 cipher
107 .decrypt_in_place(&nonce, &additional_data, &mut body[0..body_len], &tag)
108 .map_err(|_| CtxError::Rfc8446(Rfc8446Error::Decrypt))?;
109
110 right.on_decrypted(&body[0..body_len - 1]);
111
112 let d = right.on_encrypt();
113
114 if d.len() > 0 {
115 let server_key = self.application_server_key;
116 let server_nonce: [u8; 12] = match self.application_server_iv.use_and_incr() {
117 Some(cur) => cur,
118 None => return Err(CtxError::ExhaustedIv),
119 };
120
121 use ytls_record::WrappedAppStaticRecordBuilder;
122 use ytls_traits::WrappedApplicationBuilder;
123
124 let mut record_encrypt =
125 WrappedAppStaticRecordBuilder::<8192>::application_data(d)
126 .map_err(CtxError::Builder)?;
127
128 let cipher = Crypto::aead_chaha20poly1305(&server_key);
129
130 let tag = if let Ok([additional_data, encrypt_payload]) =
132 record_encrypt.as_disjoint_mut_for_aead()
133 {
134 cipher
135 .encrypt_in_place(
136 &server_nonce,
137 &additional_data,
138 encrypt_payload.as_mut(),
139 )
140 .map_err(|_| CtxError::Bug("Encrypt failure."))?
141 } else {
142 return Err(CtxError::Bug(
143 "Disjoint for AEAD failed at Application data.",
144 ));
145 };
146 record_encrypt.set_auth_tag(&tag);
147
148 lo.send_record_out(record_encrypt.as_encoded_bytes());
149 }
150 }
151
152 if remaining.len() == 0 {
153 break;
154 }
155
156 data = remaining;
157 }
158 li.left_buf_mark_discard_in(consumed);
159
160 Ok(None)
161 }
162}