Skip to main content

rustls_jls/jls/
mod.rs

1use core::ops::DerefMut;
2use std::string::String;
3
4use crate::log::trace;
5use crate::msgs::codec::Codec;
6use crate::msgs::handshake::{
7    ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, PresharedKeyBinder,
8    PresharedKeyOffer,
9};
10
11use alloc::vec;
12use alloc::vec::Vec;
13#[cfg(not(feature = "ring"))]
14use aws_lc_rs::digest::{SHA256, digest};
15#[cfg(feature = "ring")]
16use ring::digest::{SHA256, digest};
17
18// use aes_gcm to support 512bits long nonce (not supported by ring)
19use aes_gcm::{
20    AeadInPlace, // Or `Aes128Gcm`
21    AesGcm,
22    KeyInit,
23    aead::consts::U32,
24    aes::Aes256,
25};
26
27pub(crate) mod server;
28
29pub use server::JlsServerConfig;
30
31#[derive(Clone, Debug)]
32/// JLS Configuration
33pub struct JlsClientConfig {
34    /// enable JLS
35    pub enable: bool,
36    /// user password of a JLS peer
37    pub user: JlsUser,
38}
39
40/// JLS User information
41/// user_iv is generally used as username
42#[derive(Clone, Debug, PartialEq)]
43pub struct JlsUser {
44    /// user password of a JLS peer
45    pub user_pwd: String,
46    /// user iv for a JLS peer
47    pub user_iv: String,
48}
49
50impl JlsUser {
51    /// Create a new JlsUser
52    pub fn new(user_pwd: &str, user_iv: &str) -> JlsUser {
53        JlsUser {
54            user_pwd: String::from(user_pwd),
55            user_iv: String::from(user_iv),
56        }
57    }
58
59    /// Build a fake random from a true random with given keyshare
60    pub fn build_fake_random(&self, random: &[u8; 16], auth_data: &[u8]) -> [u8; 32] {
61        let mut iv = self.user_iv.as_bytes().to_vec();
62        iv.extend_from_slice(auth_data);
63        let mut pwd = self.user_pwd.as_bytes().to_vec();
64        pwd.extend_from_slice(auth_data);
65
66        trace!("generate ch iv: {:?}", iv);
67        trace!("generate pwd: {:?}", pwd);
68
69        let iv = digest(&SHA256, iv.as_ref());
70        let pwd = digest(&SHA256, pwd.as_ref());
71
72        let cipher = AesGcm::<Aes256, U32>::new(pwd.as_ref().into());
73
74        let mut buffer = Vec::<u8>::from(random.as_slice());
75        cipher
76            .encrypt_in_place(iv.as_ref().into(), b"", &mut buffer)
77            .unwrap();
78
79        buffer.try_into().unwrap()
80    }
81
82    /// Check if it's a valid fake random
83    pub fn check_fake_random(&self, fake_random: &[u8; 32], auth_data: &[u8]) -> bool {
84        let mut iv = self.user_iv.as_bytes().to_vec();
85        iv.extend_from_slice(auth_data);
86        let mut pwd = self.user_pwd.as_bytes().to_vec();
87        pwd.extend_from_slice(auth_data);
88
89        trace!("check ch iv: {:?}", iv);
90        trace!("check pwd: {:?}", pwd);
91
92        let iv = digest(&SHA256, iv.as_ref());
93        let pwd = digest(&SHA256, pwd.as_ref());
94
95        let cipher = AesGcm::<Aes256, U32>::new(pwd.as_ref().into());
96
97        let mut buffer = Vec::from(fake_random.as_ref());
98
99        let is_valid = cipher
100            .decrypt_in_place(iv.as_ref().into(), b"", &mut buffer)
101            .is_ok();
102        is_valid
103    }
104}
105
106impl Default for JlsUser {
107    fn default() -> JlsUser {
108        JlsUser {
109            user_pwd: "3070111071563328618171495819203123318".into(),
110            user_iv: "3070111071563328618171495819203123318".into(),
111        }
112    }
113}
114
115impl JlsClientConfig {
116    /// Create a new JlsConfig
117    pub fn new(user_pwd: &str, user_iv: &str) -> JlsClientConfig {
118        JlsClientConfig {
119            enable: true,
120            user: JlsUser::new(user_pwd, user_iv),
121        }
122    }
123    /// enable JLS
124    pub fn enable(mut self, enable: bool) -> Self {
125        self.enable = enable;
126        self
127    }
128    /// Set JLS user
129    pub fn set_user(mut self, user_pwd: String, user_iv: String) -> Self {
130        self.user = JlsUser::new(&user_pwd, &user_iv);
131        self
132    }
133}
134impl Default for JlsClientConfig {
135    fn default() -> JlsClientConfig {
136        JlsClientConfig {
137            enable: false,
138            user: JlsUser::default(),
139        }
140    }
141}
142
143// fill zero in the psk binders field.
144pub(crate) fn set_zero_psk_binders(chp: &ClientHelloPayload, msg: &mut [u8]) {
145    if let Some(psk) = chp.preshared_key_offer.as_ref() {
146        let mut psk = psk.clone();
147        for bind in psk.binders.iter_mut() {
148            let len = bind.as_ref().len();
149            *bind = PresharedKeyBinder::from(vec![0; len]);
150        }
151        let mut psk_bytes = Vec::new();
152        psk.binders.encode(&mut psk_bytes);
153        let len = msg.len();
154        msg[len - psk_bytes.len()..].copy_from_slice(&psk_bytes);
155        trace!("set zero psk binders: {:?}", msg);
156    }
157}
158
159/// Jls State
160#[derive(Clone, Debug, Default)]
161pub enum JlsState {
162    /// JLS authentication success
163    AuthSuccess(JlsUser),
164    /// JLS authentication failed with upstream addr
165    AuthFailed(Option<String>),
166    /// JLS authentication not yet happened
167    #[default]
168    NotAuthed,
169    /// JLS is not enabled
170    Disabled,
171}