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
59use ytls_traits::CryptoChaCha20Poly1305Processor;
60
61impl<Crypto> CtxApplicationProcessor for ServerApplicationCtx<Crypto>
62where
63 Crypto: CryptoConfig,
64{
65 type Error = CtxError;
66
67 fn spin_application<Li: TlsLeftIn, Lo: TlsLeftOut, R: TlsRight>(
68 &mut self,
69 li: &mut Li,
70 lo: &mut Lo,
71 right: &mut R,
72 ) -> Result<Option<ShutdownComplete>, Self::Error> {
73 let init_data = li.left_buf_in();
74 let init_len = init_data.len();
75 let mut data = init_data;
76
77 #[allow(unused_assignments)]
78 let mut consumed = 0;
79
80 loop {
81 if data.len() > 0 {
82 let (rec, remaining) =
83 Record::parse_client_appdata(data).map_err(|e| CtxError::Record(e))?;
84
85 consumed = init_len - remaining.len();
86
87 if let Content::ApplicationData = rec.content() {
88 let key = self.application_client_key;
89 let nonce: [u8; 12] = match self.application_client_iv.use_and_incr() {
90 Some(cur) => cur,
91 None => return Err(CtxError::ExhaustedIv),
92 };
93
94 let cipher = Crypto::aead_chaha20poly1305(&key);
95 let full_payload = rec.as_bytes();
96 let full_payload_len = full_payload.len();
97 let mut tag: [u8; 16] = [0; 16];
98
99 let body_len = full_payload_len - 16;
100 let mut body: [u8; 8192] = [0; 8192];
101 body[0..body_len].copy_from_slice(&full_payload[0..body_len]);
102 tag.copy_from_slice(&full_payload[body_len..body_len + 16]);
103 let additional_data = rec.header_as_bytes();
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 data = remaining;
111 }
112
113 let d = right.on_encrypt();
114
115 if d.len() > 0 {
116 let server_key = self.application_server_key;
117 let server_nonce: [u8; 12] = match self.application_server_iv.use_and_incr() {
118 Some(cur) => cur,
119 None => return Err(CtxError::ExhaustedIv),
120 };
121
122 use ytls_record::WrappedAppStaticRecordBuilder;
123 use ytls_traits::WrappedApplicationBuilder;
124
125 let mut record_encrypt = WrappedAppStaticRecordBuilder::<8292>::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(&server_nonce, &additional_data, encrypt_payload.as_mut())
136 .map_err(|_| CtxError::Bug("Encrypt failure."))?
137 } else {
138 return Err(CtxError::Bug(
139 "Disjoint for AEAD failed at Application data.",
140 ));
141 };
142 record_encrypt.set_auth_tag(&tag);
143
144 lo.send_record_out(record_encrypt.as_encoded_bytes());
145 }
146
147 if data.len() == 0 {
154 break;
155 }
156 }
157 if consumed > 0 {
158 li.left_buf_mark_discard_in(consumed);
159 }
160
161 Ok(None)
162 }
163}