mirror of
https://github.com/Noratrieb/tls.git
synced 2026-01-14 08:35:03 +01:00
parse helloretryrequest
This commit is contained in:
parent
2266f6f8b6
commit
a81438e7e3
4 changed files with 113 additions and 43 deletions
|
|
@ -14,6 +14,7 @@
|
||||||
llvmPackages_16.clang
|
llvmPackages_16.clang
|
||||||
llvmPackages_16.bintools
|
llvmPackages_16.bintools
|
||||||
llvmPackages_16.libllvm
|
llvmPackages_16.libllvm
|
||||||
|
llvmPackages_16.lldb
|
||||||
rustup
|
rustup
|
||||||
];
|
];
|
||||||
# https://github.com/rust-lang/rust-bindgen#environment-variables
|
# https://github.com/rust-lang/rust-bindgen#environment-variables
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,7 @@ impl ClientSetupConnection {
|
||||||
formats: vec![proto::ECPointFormat::Uncompressed].into(),
|
formats: vec![proto::ECPointFormat::Uncompressed].into(),
|
||||||
},
|
},
|
||||||
proto::ExtensionCH::SupportedGroups {
|
proto::ExtensionCH::SupportedGroups {
|
||||||
groups: vec![
|
groups: vec![proto::NamedGroup::X25519].into(),
|
||||||
proto::NamedGroup::X25519,
|
|
||||||
].into(),
|
|
||||||
},
|
},
|
||||||
proto::ExtensionCH::SupportedVersions {
|
proto::ExtensionCH::SupportedVersions {
|
||||||
versions: vec![proto::TLSV13].into(),
|
versions: vec![proto::TLSV13].into(),
|
||||||
|
|
@ -54,6 +52,7 @@ impl ClientSetupConnection {
|
||||||
plaintext.write(&mut stream)?;
|
plaintext.write(&mut stream)?;
|
||||||
stream.flush()?;
|
stream.flush()?;
|
||||||
|
|
||||||
|
println!("hello!");
|
||||||
let out = proto::TLSPlaintext::read(stream.get_mut())?;
|
let out = proto::TLSPlaintext::read(stream.get_mut())?;
|
||||||
dbg!(out);
|
dbg!(out);
|
||||||
|
|
||||||
|
|
@ -77,6 +76,7 @@ pub enum ErrorKind {
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
impl From<io::Error> for Error {
|
||||||
fn from(value: io::Error) -> Self {
|
fn from(value: io::Error) -> Self {
|
||||||
|
panic!("io error: {value}");
|
||||||
Self {
|
Self {
|
||||||
kind: ErrorKind::Io(value),
|
kind: ErrorKind::Io(value),
|
||||||
}
|
}
|
||||||
|
|
@ -85,6 +85,7 @@ impl From<io::Error> for Error {
|
||||||
|
|
||||||
impl From<ErrorKind> for Error {
|
impl From<ErrorKind> for Error {
|
||||||
fn from(value: ErrorKind) -> Self {
|
fn from(value: ErrorKind) -> Self {
|
||||||
|
panic!("error: {value:?}");
|
||||||
Self { kind: value }
|
Self { kind: value }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
107
src/proto.rs
107
src/proto.rs
|
|
@ -9,7 +9,7 @@ use byteorder::{BigEndian as B, ReadBytesExt, WriteBytesExt};
|
||||||
|
|
||||||
use crate::ErrorKind;
|
use crate::ErrorKind;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum TLSPlaintext {
|
pub enum TLSPlaintext {
|
||||||
Invalid {
|
Invalid {
|
||||||
legacy_version: ProtocolVersion,
|
legacy_version: ProtocolVersion,
|
||||||
|
|
@ -34,12 +34,9 @@ impl TLSPlaintext {
|
||||||
|
|
||||||
pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
|
pub fn write(&self, w: &mut impl Write) -> io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
TLSPlaintext::Invalid {
|
TLSPlaintext::Invalid { .. } => todo!(),
|
||||||
legacy_version,
|
|
||||||
fragment,
|
|
||||||
} => todo!(),
|
|
||||||
TLSPlaintext::ChangeCipherSpec => todo!(),
|
TLSPlaintext::ChangeCipherSpec => todo!(),
|
||||||
TLSPlaintext::Alert { alert } => todo!(),
|
TLSPlaintext::Alert { .. } => todo!(),
|
||||||
TLSPlaintext::Handshake { handshake } => {
|
TLSPlaintext::Handshake { handshake } => {
|
||||||
Self::HANDSHAKE.write(w)?;
|
Self::HANDSHAKE.write(w)?;
|
||||||
// MUST be set to 0x0303 for all records
|
// MUST be set to 0x0303 for all records
|
||||||
|
|
@ -91,13 +88,13 @@ pub type Random = [u8; 32];
|
||||||
|
|
||||||
// https://datatracker.ietf.org/doc/html/rfc8446#section-4
|
// https://datatracker.ietf.org/doc/html/rfc8446#section-4
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum Handshake: u8, (length: u24) {
|
pub enum Handshake: u8, (length: u24) {
|
||||||
// https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2
|
// https://datatracker.ietf.org/doc/html/rfc8446#section-4.1.2
|
||||||
ClientHello {
|
ClientHello {
|
||||||
legacy_version: ProtocolVersion,
|
legacy_version: ProtocolVersion,
|
||||||
random: Random,
|
random: Random,
|
||||||
legacy_session_id: List<u8, u8>,
|
legacy_session_id: LegacySessionId,
|
||||||
cipher_suites: List<CipherSuite, u16>,
|
cipher_suites: List<CipherSuite, u16>,
|
||||||
legacy_compressions_methods: List<u8, u8>,
|
legacy_compressions_methods: List<u8, u8>,
|
||||||
extensions: List<ExtensionCH, u16>,
|
extensions: List<ExtensionCH, u16>,
|
||||||
|
|
@ -105,7 +102,7 @@ proto_enum! {
|
||||||
ServerHello {
|
ServerHello {
|
||||||
legacy_version: ProtocolVersion,
|
legacy_version: ProtocolVersion,
|
||||||
random: Random,
|
random: Random,
|
||||||
legacy_session_id_echo: u8,
|
legacy_session_id_echo: LegacySessionId,
|
||||||
cipher_suite: CipherSuite,
|
cipher_suite: CipherSuite,
|
||||||
legacy_compression_method: u8,
|
legacy_compression_method: u8,
|
||||||
extensions: List<ExtensionSH, u16>,
|
extensions: List<ExtensionSH, u16>,
|
||||||
|
|
@ -122,12 +119,19 @@ proto_enum! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const HELLO_RETRY_REQUEST: [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,
|
||||||
|
];
|
||||||
|
|
||||||
pub const LEGACY_TLSV10: ProtocolVersion = 0x0301;
|
pub const LEGACY_TLSV10: ProtocolVersion = 0x0301;
|
||||||
pub const LEGACY_TLSV12: ProtocolVersion = 0x0303;
|
pub const LEGACY_TLSV12: ProtocolVersion = 0x0303;
|
||||||
pub const TLSV13: ProtocolVersion = 0x0304;
|
pub const TLSV13: ProtocolVersion = 0x0304;
|
||||||
|
|
||||||
|
type LegacySessionId = List<u8, u8>;
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum CipherSuite: [u8; 2] {
|
pub enum CipherSuite: [u8; 2] {
|
||||||
TlsAes128GcmSha256 = [0x13, 0x01],
|
TlsAes128GcmSha256 = [0x13, 0x01],
|
||||||
TlsAes256GcmSha384 = [0x13, 0x02],
|
TlsAes256GcmSha384 = [0x13, 0x02],
|
||||||
|
|
@ -138,54 +142,57 @@ proto_enum! {
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ExtensionCH: u16, (length: u16) {
|
pub enum ExtensionCH: u16, (length: u16) {
|
||||||
ServerName {
|
ServerName {
|
||||||
server_name: ServerNameList,
|
server_name: ServerNameList,
|
||||||
} = 0,
|
} = 0,
|
||||||
MaxFragmentLength = 1,
|
MaxFragmentLength { todo: Todo, } = 1,
|
||||||
StatusRequest = 5,
|
StatusRequest { todo: Todo, } = 5,
|
||||||
SupportedGroups {
|
SupportedGroups {
|
||||||
groups: NamedGroupList,
|
groups: NamedGroupList,
|
||||||
} = 10,
|
} = 10,
|
||||||
ECPointFormat {
|
ECPointFormat {
|
||||||
formats: ECPointFormatList,
|
formats: ECPointFormatList,
|
||||||
} = 11,
|
} = 11,
|
||||||
SignatureAlgorithms = 13,
|
SignatureAlgorithms{ todo: Todo, } = 13,
|
||||||
UseSrtp = 14,
|
UseSrtp{ todo: Todo, } = 14,
|
||||||
Heartbeat = 15,
|
Heartbeat { todo: Todo, }= 15,
|
||||||
ApplicationLayerProtocolNegotiation = 16,
|
ApplicationLayerProtocolNegotiation{ todo: Todo, } = 16,
|
||||||
SignedCertificateTimestamp = 18,
|
SignedCertificateTimestamp{ todo: Todo, } = 18,
|
||||||
ClientCertificateType = 19,
|
ClientCertificateType{ todo: Todo, } = 19,
|
||||||
ServerCertificateType = 20,
|
ServerCertificateType { todo: Todo, }= 20,
|
||||||
Padding = 21,
|
Padding{ todo: Todo, } = 21,
|
||||||
PreSharedKey = 41,
|
PreSharedKey { todo: Todo, }= 41,
|
||||||
EarlyData = 42,
|
EarlyData{ todo: Todo, } = 42,
|
||||||
SupportedVersions {
|
SupportedVersions {
|
||||||
versions: List<ProtocolVersion, u8>,
|
versions: List<ProtocolVersion, u8>,
|
||||||
} = 43,
|
} = 43,
|
||||||
Cookie = 44,
|
Cookie{ todo: Todo, } = 44,
|
||||||
PskKeyExchangeModes = 45,
|
PskKeyExchangeModes { todo: Todo, }= 45,
|
||||||
CertificateAuthorities = 47,
|
CertificateAuthorities { todo: Todo, }= 47,
|
||||||
PostHandshakeAuth = 49,
|
PostHandshakeAuth { todo: Todo, }= 49,
|
||||||
SignatureAlgorithmsCert = 50,
|
SignatureAlgorithmsCert{ todo: Todo, } = 50,
|
||||||
KeyShare = 51,
|
KeyShare { todo: Todo, }= 51,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ExtensionSH: u16 {
|
pub enum ExtensionSH: u16, (length: u16) {
|
||||||
PreSharedKey = 41,
|
PreSharedKey = 41,
|
||||||
SupportedVersions {
|
SupportedVersions {
|
||||||
selected_version: ProtocolVersion,
|
selected_version: ProtocolVersion,
|
||||||
} = 43,
|
} = 43,
|
||||||
KeyShare = 51,
|
Cookie { todo: Todo, } = 44,
|
||||||
|
KeyShare {
|
||||||
|
group: NamedGroup,
|
||||||
|
} = 51,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ServerName: u8 {
|
pub enum ServerName: u8 {
|
||||||
HostName {
|
HostName {
|
||||||
host_name: HostName,
|
host_name: HostName,
|
||||||
|
|
@ -197,7 +204,7 @@ type HostName = List<u8, u16>;
|
||||||
type ServerNameList = List<ServerName, u16>;
|
type ServerNameList = List<ServerName, u16>;
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum ECPointFormat: u8 {
|
pub enum ECPointFormat: u8 {
|
||||||
Uncompressed = 0,
|
Uncompressed = 0,
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +212,7 @@ proto_enum! {
|
||||||
type ECPointFormatList = List<ECPointFormat, u8>;
|
type ECPointFormatList = List<ECPointFormat, u8>;
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum NamedGroup: u16 {
|
pub enum NamedGroup: u16 {
|
||||||
/* Elliptic Curve Groups (ECDHE) */
|
/* Elliptic Curve Groups (ECDHE) */
|
||||||
Secp256r1 = 0x0017,
|
Secp256r1 = 0x0017,
|
||||||
|
|
@ -225,7 +232,7 @@ proto_enum! {
|
||||||
type NamedGroupList = List<NamedGroup, u16>;
|
type NamedGroupList = List<NamedGroup, u16>;
|
||||||
|
|
||||||
proto_struct! {
|
proto_struct! {
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub struct Alert {
|
pub struct Alert {
|
||||||
level: AlertLevel,
|
level: AlertLevel,
|
||||||
description: AlertDescription,
|
description: AlertDescription,
|
||||||
|
|
@ -233,7 +240,7 @@ proto_struct! {
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum AlertLevel: u8 {
|
pub enum AlertLevel: u8 {
|
||||||
Warning = 1,
|
Warning = 1,
|
||||||
Fatal = 2,
|
Fatal = 2,
|
||||||
|
|
@ -241,7 +248,7 @@ proto_enum! {
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_enum! {
|
proto_enum! {
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum AlertDescription: u8 {
|
pub enum AlertDescription: u8 {
|
||||||
CloseNotify = 0,
|
CloseNotify = 0,
|
||||||
UnexpectedMessage = 10,
|
UnexpectedMessage = 10,
|
||||||
|
|
@ -408,7 +415,7 @@ macro_rules! proto_enum {
|
||||||
},
|
},
|
||||||
)*
|
)*
|
||||||
|
|
||||||
_ => Err(ErrorKind::InvalidFrame(Box::new(kind)).into()),
|
_ => Err(ErrorKind::InvalidFrame(Box::new(format!("invalid discriminant for {}: 0x{kind:x?}", stringify!($name)))).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -435,7 +442,24 @@ macro_rules! proto_enum {
|
||||||
}
|
}
|
||||||
use proto_enum;
|
use proto_enum;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct Todo;
|
||||||
|
|
||||||
|
impl Value for Todo {
|
||||||
|
fn write<W: Write>(&self, w: &mut W) -> io::Result<()> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read<R: Read>(r: &mut R) -> crate::Result<Self> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn byte_size(&self) -> usize {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub struct List<T, Len>(Vec<T>, PhantomData<Len>);
|
pub struct List<T, Len>(Vec<T>, PhantomData<Len>);
|
||||||
|
|
||||||
impl<T, Len: Value> From<Vec<T>> for List<T, Len> {
|
impl<T, Len: Value> From<Vec<T>> for List<T, Len> {
|
||||||
|
|
@ -605,3 +629,6 @@ macro_rules! discard {
|
||||||
($($tt:tt)*) => {};
|
($($tt:tt)*) => {};
|
||||||
}
|
}
|
||||||
use discard;
|
use discard;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
|
||||||
41
src/proto/tests.rs
Normal file
41
src/proto/tests.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn parse_hello_retry_request() {
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let mut bytes: &[u8] = &[
|
||||||
|
0x16, 0x03, 0x03, 0x00, 0x58, 0x02, 0x00, 0x00, 0x54, 0x03, 0x03, 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, 0x20, 0xdd, 0x0f, 0x25, 0x0a,
|
||||||
|
0xf0, 0xa6, 0xd9, 0xb0, 0x1c, 0x28, 0x2f, 0x55, 0xcb, 0xab, 0x07, 0x94, 0x2e, 0xb3, 0x98, 0x96,
|
||||||
|
0x32, 0x81, 0xad, 0x8d, 0x24, 0x72, 0x52, 0x2a, 0x45, 0x26, 0x10, 0xa2, 0x13, 0x01, 0x00, 0x00,
|
||||||
|
0x0c, 0x00, 0x2b, 0x00, 0x02, 0x03, 0x04, 0x00, 0x33, 0x00, 0x02, 0x00, 0x1d,
|
||||||
|
];
|
||||||
|
|
||||||
|
let handshake = TLSPlaintext::read(&mut bytes).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
handshake,
|
||||||
|
TLSPlaintext::Handshake {
|
||||||
|
handshake: Handshake::ServerHello {
|
||||||
|
legacy_version: LEGACY_TLSV12,
|
||||||
|
random: HELLO_RETRY_REQUEST,
|
||||||
|
legacy_session_id_echo:
|
||||||
|
b"\xdd\x0f\x25\x0a\xf0\xa6\xd9\xb0\x1c\x28\x2f\x55\xcb\xab\x07\x94\
|
||||||
|
\x2e\xb3\x98\x96\x32\x81\xad\x8d\x24\x72\x52\x2a\x45\x26\x10\xa2"
|
||||||
|
.to_vec()
|
||||||
|
.into(),
|
||||||
|
cipher_suite: CipherSuite::TlsAes128GcmSha256,
|
||||||
|
legacy_compression_method: 0,
|
||||||
|
extensions: vec![
|
||||||
|
ExtensionSH::SupportedVersions {
|
||||||
|
selected_version: TLSV13
|
||||||
|
},
|
||||||
|
ExtensionSH::KeyShare {
|
||||||
|
group: NamedGroup::X25519
|
||||||
|
}
|
||||||
|
]
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue