Skip to main content

ytls_server/server_ctx/
s_application.rs

1//! yTLS Server Application Ctx
2
3use 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/// yTLS Server Application Ctx
19#[cfg_attr(feature = "zeroize", derive(Zeroize, ZeroizeOnDrop))]
20pub struct ServerApplicationCtx<Crypto> {
21    //crypto: Crypto,
22    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                // TODO: transcript
131                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 remaining.len() == 0 {
148            //    break;
149            //}
150
151            //data = remaining;
152
153            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}