use core::ops::DerefMut;
use std::string::String;
use crate::log::trace;
use crate::msgs::codec::Codec;
use crate::msgs::handshake::{
ClientHelloPayload, HandshakeMessagePayload, HandshakePayload, PresharedKeyBinder,
PresharedKeyOffer,
};
use alloc::vec;
use alloc::vec::Vec;
#[cfg(not(feature = "ring"))]
use aws_lc_rs::digest::{SHA256, digest};
#[cfg(feature = "ring")]
use ring::digest::{SHA256, digest};
use aes_gcm::{
AeadInPlace, AesGcm,
KeyInit,
aead::consts::U32,
aes::Aes256,
};
pub(crate) mod server;
pub use server::JlsServerConfig;
#[derive(Clone, Debug)]
pub struct JlsClientConfig {
pub enable: bool,
pub user: JlsUser,
}
#[derive(Clone, Debug, PartialEq)]
pub struct JlsUser {
pub user_pwd: String,
pub user_iv: String,
}
impl JlsUser {
pub fn new(user_pwd: &str, user_iv: &str) -> JlsUser {
JlsUser {
user_pwd: String::from(user_pwd),
user_iv: String::from(user_iv),
}
}
pub fn build_fake_random(&self, random: &[u8; 16], auth_data: &[u8]) -> [u8; 32] {
let mut iv = self.user_iv.as_bytes().to_vec();
iv.extend_from_slice(auth_data);
let mut pwd = self.user_pwd.as_bytes().to_vec();
pwd.extend_from_slice(auth_data);
trace!("generate ch iv: {:?}", iv);
trace!("generate pwd: {:?}", pwd);
let iv = digest(&SHA256, iv.as_ref());
let pwd = digest(&SHA256, pwd.as_ref());
let cipher = AesGcm::<Aes256, U32>::new(pwd.as_ref().into());
let mut buffer = Vec::<u8>::from(random.as_slice());
cipher
.encrypt_in_place(iv.as_ref().into(), b"", &mut buffer)
.unwrap();
buffer.try_into().unwrap()
}
pub fn check_fake_random(&self, fake_random: &[u8; 32], auth_data: &[u8]) -> bool {
let mut iv = self.user_iv.as_bytes().to_vec();
iv.extend_from_slice(auth_data);
let mut pwd = self.user_pwd.as_bytes().to_vec();
pwd.extend_from_slice(auth_data);
trace!("check ch iv: {:?}", iv);
trace!("check pwd: {:?}", pwd);
let iv = digest(&SHA256, iv.as_ref());
let pwd = digest(&SHA256, pwd.as_ref());
let cipher = AesGcm::<Aes256, U32>::new(pwd.as_ref().into());
let mut buffer = Vec::from(fake_random.as_ref());
let is_valid = cipher
.decrypt_in_place(iv.as_ref().into(), b"", &mut buffer)
.is_ok();
is_valid
}
}
impl Default for JlsUser {
fn default() -> JlsUser {
JlsUser {
user_pwd: "3070111071563328618171495819203123318".into(),
user_iv: "3070111071563328618171495819203123318".into(),
}
}
}
impl JlsClientConfig {
pub fn new(user_pwd: &str, user_iv: &str) -> JlsClientConfig {
JlsClientConfig {
enable: true,
user: JlsUser::new(user_pwd, user_iv),
}
}
pub fn enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}
pub fn set_user(mut self, user_pwd: String, user_iv: String) -> Self {
self.user = JlsUser::new(&user_pwd, &user_iv);
self
}
}
impl Default for JlsClientConfig {
fn default() -> JlsClientConfig {
JlsClientConfig {
enable: false,
user: JlsUser::default(),
}
}
}
pub(crate) fn set_zero_psk_binders(chp: &ClientHelloPayload, msg: &mut [u8]) {
if let Some(psk) = chp.preshared_key_offer.as_ref() {
let mut psk = psk.clone();
for bind in psk.binders.iter_mut() {
let len = bind.as_ref().len();
*bind = PresharedKeyBinder::from(vec![0; len]);
}
let mut psk_bytes = Vec::new();
psk.binders.encode(&mut psk_bytes);
let len = msg.len();
msg[len - psk_bytes.len()..].copy_from_slice(&psk_bytes);
trace!("set zero psk binders: {:?}", msg);
}
}
#[derive(Clone, Debug, Default)]
pub enum JlsState {
AuthSuccess(JlsUser),
AuthFailed(Option<String>),
#[default]
NotAuthed,
Disabled,
}