use super::{
NamedGroup,
extension::{KeyShareServerHello, PskServerHello, ServerHelloExtension},
};
use rand::{RngCore, rngs::OsRng};
use crate::{CipherSuite, TlsVersion};
const SERVER_HELLO_RETRY_RANDOM: [u8; 32] = [
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C,
];
#[derive(Debug)]
pub struct ServerHello {
random: [u8; 32],
legacy_session_id_echo: Vec<u8>,
extensions: Vec<ServerHelloExtension>,
}
impl ServerHello {
pub fn new(
legacy_session_id_echo: &[u8],
key: &[u8; 65],
selected_identity: Option<u16>,
) -> Self {
let mut random: [u8; 32] = [0; 32];
OsRng.fill_bytes(&mut random);
let mut extensions: Vec<ServerHelloExtension> = Vec::with_capacity(3);
extensions.push(ServerHelloExtension::SupportedVersions(TlsVersion::V1_3));
if let Some(selected_identity_idx) = selected_identity {
extensions.push(ServerHelloExtension::PreSharedKey(PskServerHello::new(
selected_identity_idx,
)));
}
extensions.push(ServerHelloExtension::KeyShareServerHello(
KeyShareServerHello::new_secp256r1(key),
));
ServerHello {
random,
legacy_session_id_echo: legacy_session_id_echo.to_vec(),
extensions,
}
}
pub fn new_retry(legacy_session_id_echo: &[u8], selected_identity: Option<u16>) -> Self {
let mut extensions: Vec<ServerHelloExtension> = Vec::with_capacity(3);
extensions.push(ServerHelloExtension::SupportedVersions(TlsVersion::V1_3));
if let Some(selected_identity_idx) = selected_identity {
extensions.push(ServerHelloExtension::PreSharedKey(PskServerHello::new(
selected_identity_idx,
)));
}
extensions.push(ServerHelloExtension::KeyShareHelloRetryRequest(
NamedGroup::secp256r1,
));
ServerHello {
random: SERVER_HELLO_RETRY_RANDOM,
legacy_session_id_echo: legacy_session_id_echo.to_vec(),
extensions,
}
}
pub fn ser(self) -> Vec<u8> {
let mut buf: Vec<u8> = Vec::new();
buf.extend_from_slice(&[0x03, 0x03]);
buf.extend_from_slice(&self.random);
buf.extend_from_slice(&self.legacy_session_id_echo);
buf.extend_from_slice(&u16::from(CipherSuite::TLS_AES_128_GCM_SHA256).to_be_bytes());
buf.push(0);
let extensions_len_idx: usize = buf.len();
buf.extend_from_slice(&0_u16.to_be_bytes());
let mut extensions_len: u16 = 0;
for extension in &self.extensions {
let data: Vec<u8> = extension.ser();
let data_len: u16 = data.len().try_into().unwrap();
extensions_len = extensions_len.checked_add(data_len).unwrap();
buf.extend_from_slice(&extension.ser());
}
buf[extensions_len_idx..extensions_len_idx + 2]
.copy_from_slice(&extensions_len.to_be_bytes());
buf
}
}