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