use crate::tls::crypto::{HashAlg, derive_secret, expand_label_dyn, extract};
use alloc::vec::Vec;
pub fn server_hello_signal(
alg: HashAlg,
handshake_secret: &[u8],
transcript_hash: &[u8],
) -> [u8; 8] {
let secret = derive_secret(
alg,
handshake_secret,
b"ech accept confirmation",
transcript_hash,
);
let mut out = [0u8; 8];
expand_label_dyn(
alg,
secret.as_slice(),
b"ech accept confirmation",
b"",
&mut out,
);
out
}
pub fn hello_retry_request_signal(
alg: HashAlg,
inner_ch1_random: &[u8; 32],
transcript_hash: &[u8],
) -> [u8; 8] {
let zeros = [0u8; 64];
let salt = &zeros[..alg.output_len()];
let prk = extract(alg, salt, inner_ch1_random);
let mut out = [0u8; 8];
expand_label_dyn(
alg,
prk.as_slice(),
b"hrr ech accept confirmation",
transcript_hash,
&mut out,
);
out
}
pub fn signals_eq_ct(a: &[u8; 8], b: &[u8; 8]) -> bool {
let mut acc = 0u8;
for i in 0..8 {
acc |= a[i] ^ b[i];
}
acc == 0
}
pub fn patch_random_tail(random: &[u8; 32], signal: &[u8; 8]) -> [u8; 32] {
let mut out = *random;
out[24..32].copy_from_slice(signal);
out
}
pub fn random_tail(random: &[u8; 32]) -> [u8; 8] {
let mut out = [0u8; 8];
out.copy_from_slice(&random[24..32]);
out
}
pub fn random_with_zero_tail(random: &[u8; 32]) -> [u8; 32] {
let mut out = *random;
for b in &mut out[24..32] {
*b = 0;
}
out
}
#[allow(dead_code)]
pub(crate) fn signal_to_vec(signal: &[u8; 8]) -> Vec<u8> {
signal.to_vec()
}
pub(crate) fn locate_hrr_ech_signal_payload(handshake_msg: &[u8]) -> Option<usize> {
use crate::tls::codec::{ExtensionType, hs_type};
if handshake_msg.len() < 4 || handshake_msg[0] != hs_type::SERVER_HELLO {
return None;
}
let body_len = ((handshake_msg[1] as usize) << 16)
| ((handshake_msg[2] as usize) << 8)
| (handshake_msg[3] as usize);
if 4 + body_len != handshake_msg.len() {
return None;
}
let body = &handshake_msg[4..];
if body.len() < 2 + 32 + 1 {
return None;
}
let mut idx = 2 + 32;
let sid_len = body[idx] as usize;
idx += 1;
if idx + sid_len + 2 + 1 + 2 > body.len() {
return None;
}
idx += sid_len + 2 + 1; let ext_total = ((body[idx] as usize) << 8) | (body[idx + 1] as usize);
idx += 2;
if idx + ext_total > body.len() {
return None;
}
let ext_start_in_body = idx;
let ext_end_in_body = idx + ext_total;
let mut p = ext_start_in_body;
while p + 4 <= ext_end_in_body {
let ty = ((body[p] as u16) << 8) | (body[p + 1] as u16);
let bl = ((body[p + 2] as usize) << 8) | (body[p + 3] as usize);
let body_start = p + 4;
let body_end = body_start + bl;
if body_end > ext_end_in_body {
return None;
}
if ty == ExtensionType::ENCRYPTED_CLIENT_HELLO.0 && bl == 8 {
return Some(4 + body_start);
}
p = body_end;
}
None
}