mirror of
https://github.com/telemt/telemt.git
synced 2026-06-19 02:00:08 +07:00
Fix for TLS-F, ALPN и SNI/ALPN helpers
Co-Authored-By: brekotis <93345790+brekotis@users.noreply.github.com>
This commit is contained in:
@@ -10,11 +10,52 @@ use std::time::{Duration, Instant};
|
||||
use tokio::sync::Barrier;
|
||||
|
||||
fn make_valid_tls_handshake(secret: &[u8], timestamp: u32) -> Vec<u8> {
|
||||
const TLS_AES_128_GCM_SHA256: [u8; 2] = [0x13, 0x01];
|
||||
const TLS_EXTENSION_KEY_SHARE: u16 = 0x0033;
|
||||
const X25519_KEY_SHARE_LEN: usize = 32;
|
||||
let session_id_len: usize = 32;
|
||||
let len = tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN + 1 + session_id_len;
|
||||
let mut handshake = vec![0x42u8; len];
|
||||
let fill = 0x42u8;
|
||||
|
||||
handshake[tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN] = session_id_len as u8;
|
||||
let mut extensions = Vec::new();
|
||||
let mut key_share = Vec::new();
|
||||
key_share.extend_from_slice(&tls::TLS_NAMED_GROUP_X25519.to_be_bytes());
|
||||
key_share.extend_from_slice(&(X25519_KEY_SHARE_LEN as u16).to_be_bytes());
|
||||
key_share.push(9);
|
||||
key_share.resize(key_share.len() + X25519_KEY_SHARE_LEN - 1, 0);
|
||||
|
||||
let mut key_share_extension = Vec::new();
|
||||
key_share_extension.extend_from_slice(&(key_share.len() as u16).to_be_bytes());
|
||||
key_share_extension.extend_from_slice(&key_share);
|
||||
extensions.extend_from_slice(&TLS_EXTENSION_KEY_SHARE.to_be_bytes());
|
||||
extensions.extend_from_slice(&(key_share_extension.len() as u16).to_be_bytes());
|
||||
extensions.extend_from_slice(&key_share_extension);
|
||||
|
||||
let body_len =
|
||||
2 + 32 + 1 + session_id_len + 2 + TLS_AES_128_GCM_SHA256.len() + 1 + 1 + 2
|
||||
+ extensions.len();
|
||||
let mut body = Vec::with_capacity(body_len);
|
||||
body.extend_from_slice(&TLS_VERSION);
|
||||
body.extend_from_slice(&[fill; 32]);
|
||||
body.push(session_id_len as u8);
|
||||
body.extend_from_slice(&[fill; 32]);
|
||||
body.extend_from_slice(&(TLS_AES_128_GCM_SHA256.len() as u16).to_be_bytes());
|
||||
body.extend_from_slice(&TLS_AES_128_GCM_SHA256);
|
||||
body.push(1);
|
||||
body.push(0);
|
||||
body.extend_from_slice(&(extensions.len() as u16).to_be_bytes());
|
||||
body.extend_from_slice(&extensions);
|
||||
assert_eq!(body.len(), body_len);
|
||||
|
||||
let mut handshake = Vec::with_capacity(5 + 4 + body_len);
|
||||
handshake.push(TLS_RECORD_HANDSHAKE);
|
||||
handshake.extend_from_slice(&[0x03, 0x01]);
|
||||
handshake.extend_from_slice(&((4 + body_len) as u16).to_be_bytes());
|
||||
handshake.push(0x01);
|
||||
let body_len_bytes = (body_len as u32).to_be_bytes();
|
||||
handshake.extend_from_slice(&body_len_bytes[1..4]);
|
||||
handshake.extend_from_slice(&body);
|
||||
|
||||
// The proxy authenticates TLS-fronted clients through the random field.
|
||||
handshake[tls::TLS_DIGEST_POS..tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN].fill(0);
|
||||
|
||||
let computed = sha256_hmac(secret, &handshake);
|
||||
@@ -34,6 +75,9 @@ fn make_valid_tls_client_hello_with_alpn(
|
||||
timestamp: u32,
|
||||
alpn_protocols: &[&[u8]],
|
||||
) -> Vec<u8> {
|
||||
const TLS_EXTENSION_KEY_SHARE: u16 = 0x0033;
|
||||
const X25519_KEY_SHARE_LEN: usize = 32;
|
||||
|
||||
let mut body = Vec::new();
|
||||
body.extend_from_slice(&TLS_VERSION);
|
||||
body.extend_from_slice(&[0u8; 32]);
|
||||
@@ -45,6 +89,19 @@ fn make_valid_tls_client_hello_with_alpn(
|
||||
body.push(0);
|
||||
|
||||
let mut ext_blob = Vec::new();
|
||||
let mut key_share = Vec::new();
|
||||
key_share.extend_from_slice(&tls::TLS_NAMED_GROUP_X25519.to_be_bytes());
|
||||
key_share.extend_from_slice(&(X25519_KEY_SHARE_LEN as u16).to_be_bytes());
|
||||
key_share.push(9);
|
||||
key_share.resize(key_share.len() + X25519_KEY_SHARE_LEN - 1, 0);
|
||||
|
||||
let mut key_share_extension = Vec::new();
|
||||
key_share_extension.extend_from_slice(&(key_share.len() as u16).to_be_bytes());
|
||||
key_share_extension.extend_from_slice(&key_share);
|
||||
ext_blob.extend_from_slice(&TLS_EXTENSION_KEY_SHARE.to_be_bytes());
|
||||
ext_blob.extend_from_slice(&(key_share_extension.len() as u16).to_be_bytes());
|
||||
ext_blob.extend_from_slice(&key_share_extension);
|
||||
|
||||
if !alpn_protocols.is_empty() {
|
||||
let mut alpn_list = Vec::new();
|
||||
for proto in alpn_protocols {
|
||||
@@ -92,6 +149,9 @@ fn make_valid_tls_client_hello_with_sni_and_alpn(
|
||||
sni_host: &str,
|
||||
alpn_protocols: &[&[u8]],
|
||||
) -> Vec<u8> {
|
||||
const TLS_EXTENSION_KEY_SHARE: u16 = 0x0033;
|
||||
const X25519_KEY_SHARE_LEN: usize = 32;
|
||||
|
||||
let mut body = Vec::new();
|
||||
body.extend_from_slice(&TLS_VERSION);
|
||||
body.extend_from_slice(&[0u8; 32]);
|
||||
@@ -114,6 +174,19 @@ fn make_valid_tls_client_hello_with_sni_and_alpn(
|
||||
ext_blob.extend_from_slice(&(sni_payload.len() as u16).to_be_bytes());
|
||||
ext_blob.extend_from_slice(&sni_payload);
|
||||
|
||||
let mut key_share = Vec::new();
|
||||
key_share.extend_from_slice(&tls::TLS_NAMED_GROUP_X25519.to_be_bytes());
|
||||
key_share.extend_from_slice(&(X25519_KEY_SHARE_LEN as u16).to_be_bytes());
|
||||
key_share.push(9);
|
||||
key_share.resize(key_share.len() + X25519_KEY_SHARE_LEN - 1, 0);
|
||||
|
||||
let mut key_share_extension = Vec::new();
|
||||
key_share_extension.extend_from_slice(&(key_share.len() as u16).to_be_bytes());
|
||||
key_share_extension.extend_from_slice(&key_share);
|
||||
ext_blob.extend_from_slice(&TLS_EXTENSION_KEY_SHARE.to_be_bytes());
|
||||
ext_blob.extend_from_slice(&(key_share_extension.len() as u16).to_be_bytes());
|
||||
ext_blob.extend_from_slice(&key_share_extension);
|
||||
|
||||
if !alpn_protocols.is_empty() {
|
||||
let mut alpn_list = Vec::new();
|
||||
for proto in alpn_protocols {
|
||||
@@ -549,25 +622,6 @@ async fn adversarial_tls_replay_churn_allows_only_unique_digests() {
|
||||
let replay_checker = Arc::new(ReplayChecker::new(8192, Duration::from_secs(60)));
|
||||
let rng = Arc::new(SecureRandom::new());
|
||||
|
||||
let make_tagged_handshake = |timestamp: u32, tag: u8| {
|
||||
let session_id_len: usize = 32;
|
||||
let len = tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN + 1 + session_id_len;
|
||||
let mut handshake = vec![tag; len];
|
||||
|
||||
handshake[tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN] = session_id_len as u8;
|
||||
handshake[tls::TLS_DIGEST_POS..tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN].fill(0);
|
||||
let computed = sha256_hmac(&secret, &handshake);
|
||||
let mut digest = computed;
|
||||
let ts = timestamp.to_le_bytes();
|
||||
for i in 0..4 {
|
||||
digest[28 + i] ^= ts[i];
|
||||
}
|
||||
|
||||
handshake[tls::TLS_DIGEST_POS..tls::TLS_DIGEST_POS + tls::TLS_DIGEST_LEN]
|
||||
.copy_from_slice(&digest);
|
||||
handshake
|
||||
};
|
||||
|
||||
let mut tasks = Vec::new();
|
||||
|
||||
// 128 exact duplicates: only one should pass.
|
||||
@@ -601,7 +655,7 @@ async fn adversarial_tls_replay_churn_allows_only_unique_digests() {
|
||||
let config = Arc::clone(&config);
|
||||
let replay_checker = Arc::clone(&replay_checker);
|
||||
let rng = Arc::clone(&rng);
|
||||
let handshake = make_tagged_handshake(10_000 + i as u32, (i as u8).wrapping_add(0x80));
|
||||
let handshake = make_valid_tls_handshake(&secret, 10_000 + i as u32);
|
||||
tasks.push(tokio::spawn(async move {
|
||||
let peer = SocketAddr::new(
|
||||
IpAddr::V4(Ipv4Addr::new(198, 18, 0, ((i % 250) + 1) as u8)),
|
||||
|
||||
Reference in New Issue
Block a user