extension: divide
This commit is contained in:
parent
1dbf7b6fe0
commit
25f9619f4f
|
@ -86,7 +86,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||||
|
|
||||||
pub fn tls_connect<DeviceT>(
|
pub fn tls_connect<DeviceT>(
|
||||||
&mut self,
|
&mut self,
|
||||||
iface: EthernetInterface<DeviceT>,
|
iface: &mut EthernetInterface<DeviceT>,
|
||||||
sockets: &mut SocketSet,
|
sockets: &mut SocketSet,
|
||||||
now: Instant
|
now: Instant
|
||||||
) -> Result<bool>
|
) -> Result<bool>
|
||||||
|
@ -193,7 +193,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||||
cipher_suites: &cipher_suites,
|
cipher_suites: &cipher_suites,
|
||||||
compression_method_length: 1,
|
compression_method_length: 1,
|
||||||
compression_methods: 0,
|
compression_methods: 0,
|
||||||
extension_length: supported_versions_extension.get_length(),
|
extension_length: supported_versions_extension.get_length().try_into().unwrap(),
|
||||||
extensions: vec![
|
extensions: vec![
|
||||||
supported_versions_extension,
|
supported_versions_extension,
|
||||||
signature_algorithms_extension,
|
signature_algorithms_extension,
|
||||||
|
@ -208,7 +208,7 @@ impl<R: RngCore + CryptoRng> TlsSocket<R> {
|
||||||
for ext in client_hello.extensions.iter() {
|
for ext in client_hello.extensions.iter() {
|
||||||
sum += ext.get_length();
|
sum += ext.get_length();
|
||||||
}
|
}
|
||||||
sum
|
sum.try_into().unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let handshake_repr = HandshakeRepr {
|
let handshake_repr = HandshakeRepr {
|
||||||
|
@ -390,7 +390,7 @@ impl<'a> TlsBuffer<'a> {
|
||||||
self.enqueue_extensions(client_hello.extensions)
|
self.enqueue_extensions(client_hello.extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enqueue_extensions(&mut self, extensions: Vec<Extension<'a>>) -> Result<()> {
|
fn enqueue_extensions(&mut self, extensions: Vec<Extension>) -> Result<()> {
|
||||||
for extension in extensions {
|
for extension in extensions {
|
||||||
self.write_u16(extension.extension_type.into())?;
|
self.write_u16(extension.extension_type.into())?;
|
||||||
self.write_u16(extension.length)?;
|
self.write_u16(extension.length)?;
|
||||||
|
|
|
@ -5,6 +5,8 @@ use num_enum::TryFromPrimitive;
|
||||||
use rand_core::RngCore;
|
use rand_core::RngCore;
|
||||||
use rand_core::CryptoRng;
|
use rand_core::CryptoRng;
|
||||||
|
|
||||||
|
use p256::{EncodedPoint, AffinePoint, ecdh::EphemeralSecret};
|
||||||
|
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use core::convert::TryInto;
|
use core::convert::TryInto;
|
||||||
|
|
||||||
|
@ -52,10 +54,19 @@ impl<'a> TlsRepr<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn client_hello(mut self) -> Self {
|
pub(crate) fn client_hello<T>(mut self, rng: &mut T) -> Self
|
||||||
|
where
|
||||||
|
T: RngCore + CryptoRng
|
||||||
|
{
|
||||||
self.content_type = TlsContentType::Handshake;
|
self.content_type = TlsContentType::Handshake;
|
||||||
self.version = TlsVersion::Tls10;
|
self.version = TlsVersion::Tls10;
|
||||||
// TODO: Fill in handshake field
|
self.handshake = Some({
|
||||||
|
let mut repr = HandshakeRepr::new();
|
||||||
|
repr.handshake_data = HandshakeData::ClientHello({
|
||||||
|
ClientHello::new(rng)
|
||||||
|
});
|
||||||
|
repr
|
||||||
|
});
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +114,7 @@ impl<'a, 'b> HandshakeRepr<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||||
#[allow(non_camel_case)]
|
#[allow(non_camel_case_types)]
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
pub(crate) enum CipherSuite {
|
pub(crate) enum CipherSuite {
|
||||||
TLS_AES_128_GCM_SHA256 = 0x1301,
|
TLS_AES_128_GCM_SHA256 = 0x1301,
|
||||||
|
@ -124,7 +135,7 @@ pub(crate) struct ClientHello<'a> {
|
||||||
pub(crate) compression_method_length: u8, // Legacy: Must be 1, to contain a byte
|
pub(crate) compression_method_length: u8, // Legacy: Must be 1, to contain a byte
|
||||||
pub(crate) compression_methods: u8, // Legacy: Must be 1 byte of 0
|
pub(crate) compression_methods: u8, // Legacy: Must be 1 byte of 0
|
||||||
pub(crate) extension_length: u16,
|
pub(crate) extension_length: u16,
|
||||||
pub(crate) extensions: Vec<Extension<'a>>,
|
pub(crate) extensions: Vec<Extension>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -169,9 +180,162 @@ impl<'a> ClientHello<'a> {
|
||||||
rng.fill_bytes(&mut client_hello.random);
|
rng.fill_bytes(&mut client_hello.random);
|
||||||
rng.fill_bytes(&mut client_hello.session_id);
|
rng.fill_bytes(&mut client_hello.session_id);
|
||||||
|
|
||||||
|
client_hello.add_ch_supported_versions();
|
||||||
|
client_hello.add_sig_algs();
|
||||||
|
client_hello.add_client_groups_with_key_shares(&mut rng);
|
||||||
|
|
||||||
client_hello
|
client_hello
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_ch_supported_versions(mut self) -> Self {
|
||||||
|
let length = 2;
|
||||||
|
let mut versions = Vec::new();
|
||||||
|
versions.push(TlsVersion::Tls13);
|
||||||
|
|
||||||
|
let mut content = SupportedVersions::ClientHello {
|
||||||
|
length,
|
||||||
|
versions,
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension_data = ExtensionData::SupportedVersions(content);
|
||||||
|
let length = extension_data.get_length();
|
||||||
|
let extension = Extension {
|
||||||
|
extension_type: ExtensionType::SupportedVersions,
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
extension_data,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.extensions.push(extension);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_sh_supported_versions(mut self) -> Self {
|
||||||
|
let selected_version = TlsVersion::Tls13;
|
||||||
|
|
||||||
|
let mut content = SupportedVersions::ServerHello {
|
||||||
|
selected_version
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension_data = ExtensionData::SupportedVersions(content);
|
||||||
|
let length = extension_data.get_length();
|
||||||
|
let extension = Extension {
|
||||||
|
extension_type: ExtensionType::SupportedVersions,
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
extension_data,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.extensions.push(extension);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_sig_algs(mut self) -> Self {
|
||||||
|
let mut algorithms = Vec::new();
|
||||||
|
{
|
||||||
|
use SignatureScheme::*;
|
||||||
|
algorithms.push(ecdsa_secp256r1_sha256);
|
||||||
|
algorithms.push(ed25519);
|
||||||
|
algorithms.push(rsa_pss_pss_sha256);
|
||||||
|
algorithms.push(rsa_pkcs1_sha256);
|
||||||
|
algorithms.push(rsa_pss_rsae_sha256);
|
||||||
|
algorithms.push(rsa_pss_pss_sha384);
|
||||||
|
algorithms.push(rsa_pkcs1_sha384);
|
||||||
|
algorithms.push(rsa_pss_rsae_sha384);
|
||||||
|
algorithms.push(rsa_pss_pss_sha512);
|
||||||
|
algorithms.push(rsa_pkcs1_sha512);
|
||||||
|
algorithms.push(rsa_pss_rsae_sha512);
|
||||||
|
}
|
||||||
|
let length = algorithms.len() * 2;
|
||||||
|
|
||||||
|
let list = SignatureSchemeList {
|
||||||
|
supported_signature_algorithms: algorithms,
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let extension_data = ExtensionData::SignatureAlgorithms(list);
|
||||||
|
let length = extension_data.get_length();
|
||||||
|
let extension = Extension {
|
||||||
|
extension_type: ExtensionType::SignatureAlgorithms,
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
extension_data
|
||||||
|
};
|
||||||
|
|
||||||
|
self.extensions.push(extension);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn add_client_groups_with_key_shares<T>(mut self, rng: &mut T) -> Self
|
||||||
|
where
|
||||||
|
T: RngCore + CryptoRng
|
||||||
|
{
|
||||||
|
// List out all supported groups
|
||||||
|
let mut list = Vec::new();
|
||||||
|
list.push(NamedGroup::secp256r1);
|
||||||
|
|
||||||
|
let length = list.len()*2;
|
||||||
|
|
||||||
|
// Use the list to generate all key shares and store in a vec
|
||||||
|
let client_shares = Vec::new();
|
||||||
|
let client_shares_length = 0;
|
||||||
|
for named_group in list.iter() {
|
||||||
|
let mut key_exchange = Vec::new();
|
||||||
|
let key_share_entry = match named_group {
|
||||||
|
NamedGroup::secp256r1 => {
|
||||||
|
let ecdh_secret = EphemeralSecret::random(&mut rng);
|
||||||
|
let ecdh_public = EncodedPoint::from(&ecdh_secret);
|
||||||
|
|
||||||
|
let x_coor = ecdh_public.x();
|
||||||
|
let y_coor = ecdh_public.y().unwrap();
|
||||||
|
|
||||||
|
key_exchange.push(0x04); // Legacy value
|
||||||
|
key_exchange.extend_from_slice(&x_coor);
|
||||||
|
key_exchange.extend_from_slice(&y_coor);
|
||||||
|
|
||||||
|
let key_exchange_length = key_exchange.len();
|
||||||
|
|
||||||
|
KeyShareEntry {
|
||||||
|
group: *named_group,
|
||||||
|
length: key_exchange_length.try_into().unwrap(),
|
||||||
|
key_exchange
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// TODO: Implement keygen for other named groups
|
||||||
|
_ => todo!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
client_shares_length += key_share_entry.get_length();
|
||||||
|
client_shares.push(key_share_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack up the client shares into key share
|
||||||
|
let key_share_content = KeyShareEntryContent::KeyShareClientHello {
|
||||||
|
length: client_shares_length.try_into().unwrap(),
|
||||||
|
client_shares,
|
||||||
|
};
|
||||||
|
let extension_data = ExtensionData::KeyShareEntry(key_share_content);
|
||||||
|
let length = extension_data.get_length();
|
||||||
|
let key_share_extension = Extension {
|
||||||
|
extension_type: ExtensionType::KeyShare,
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
extension_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
let group_list = NamedGroupList {
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
named_group_list: list,
|
||||||
|
};
|
||||||
|
let extension_data = ExtensionData::NegotiatedGroups(group_list);
|
||||||
|
let length = extension_data.get_length();
|
||||||
|
let group_list_extension = Extension {
|
||||||
|
extension_type: ExtensionType::SupportedGroups,
|
||||||
|
length: length.try_into().unwrap(),
|
||||||
|
extension_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
self.extensions.push(group_list_extension);
|
||||||
|
self.extensions.push(key_share_extension);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_length(&self) -> u32 {
|
pub(crate) fn get_length(&self) -> u32 {
|
||||||
let mut length :u32 = 2; // TlsVersion size
|
let mut length :u32 = 2; // TlsVersion size
|
||||||
length += 32; // Random size
|
length += 32; // Random size
|
||||||
|
@ -198,7 +362,7 @@ pub(crate) struct ServerHello<'a> {
|
||||||
pub(crate) cipher_suite: CipherSuite,
|
pub(crate) cipher_suite: CipherSuite,
|
||||||
pub(crate) compression_method: u8, // Always 0
|
pub(crate) compression_method: u8, // Always 0
|
||||||
pub(crate) extension_length: u16,
|
pub(crate) extension_length: u16,
|
||||||
pub(crate) extensions: Vec<Extension<'a>>,
|
pub(crate) extensions: Vec<Extension>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||||
|
@ -234,15 +398,195 @@ impl ExtensionType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone)]
|
||||||
pub(crate) struct Extension<'a> {
|
pub(crate) struct Extension {
|
||||||
pub(crate) extension_type: ExtensionType,
|
pub(crate) extension_type: ExtensionType,
|
||||||
pub(crate) length: u16,
|
pub(crate) length: u16,
|
||||||
pub(crate) extension_data: &'a[u8],
|
pub(crate) extension_data: ExtensionData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Extension<'a> {
|
impl Extension {
|
||||||
pub(crate) fn get_length(&self) -> u16 {
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
self.extension_type.get_length() + 2 + (self.extension_data.len() as u16)
|
2 + 2 + usize::try_from(self.length).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) enum ExtensionData {
|
||||||
|
SupportedVersions(SupportedVersions),
|
||||||
|
Cookie(Cookie),
|
||||||
|
SignatureAlgorithms(SignatureSchemeList),
|
||||||
|
SignatureAlgorithmsCertificate(SignatureSchemeList),
|
||||||
|
NegotiatedGroups(NamedGroupList),
|
||||||
|
KeyShareEntry(KeyShareEntryContent),
|
||||||
|
ServerName(ServerName),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtensionData {
|
||||||
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
Self::SupportedVersions(s) => s.get_length(),
|
||||||
|
Self::SignatureAlgorithms(list) => list.get_length(),
|
||||||
|
Self::NegotiatedGroups(list) => list.get_length(),
|
||||||
|
Self::KeyShareEntry(entry_content) => entry_content.get_length(),
|
||||||
|
|
||||||
|
// Implement get_length for all textension data
|
||||||
|
_ => todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) enum SupportedVersions {
|
||||||
|
ClientHello {
|
||||||
|
length: u16,
|
||||||
|
versions: Vec<TlsVersion>,
|
||||||
|
},
|
||||||
|
ServerHello {
|
||||||
|
selected_version: TlsVersion,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SupportedVersions {
|
||||||
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
Self::ClientHello { length, versions } => {
|
||||||
|
usize::try_from(*length).unwrap() + 2
|
||||||
|
}
|
||||||
|
Self::ServerHello { selected_version } => 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct Cookie {
|
||||||
|
length: u16,
|
||||||
|
cookie: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub(crate) enum SignatureScheme {
|
||||||
|
/* RSASSA-PKCS1-v1_5 algorithms */
|
||||||
|
rsa_pkcs1_sha256 = 0x0401,
|
||||||
|
rsa_pkcs1_sha384 = 0x0501,
|
||||||
|
rsa_pkcs1_sha512 = 0x0601,
|
||||||
|
|
||||||
|
/* ECDSA algorithms */
|
||||||
|
ecdsa_secp256r1_sha256 = 0x0403,
|
||||||
|
ecdsa_secp384r1_sha384 = 0x0503,
|
||||||
|
ecdsa_secp521r1_sha512 = 0x0603,
|
||||||
|
|
||||||
|
/* RSASSA-PSS algorithms with public key OID rsaEncryption */
|
||||||
|
rsa_pss_rsae_sha256 = 0x0804,
|
||||||
|
rsa_pss_rsae_sha384 = 0x0805,
|
||||||
|
rsa_pss_rsae_sha512 = 0x0806,
|
||||||
|
|
||||||
|
/* EdDSA algorithms */
|
||||||
|
ed25519 = 0x0807,
|
||||||
|
ed488 = 0x0808,
|
||||||
|
|
||||||
|
/* RSASSA-PSS algorithms with public key OID RSASSA-PSS */
|
||||||
|
rsa_pss_pss_sha256 = 0x0809,
|
||||||
|
rsa_pss_pss_sha384 = 0x080a,
|
||||||
|
rsa_pss_pss_sha512 = 0x080b,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct SignatureSchemeList {
|
||||||
|
length: u16,
|
||||||
|
supported_signature_algorithms: Vec<SignatureScheme>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SignatureSchemeList {
|
||||||
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
|
2 + usize::try_from(self.length).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub(crate) enum NamedGroup {
|
||||||
|
/* Elliptic Curve Groups (ECDHE) */
|
||||||
|
secp256r1 = 0x0017,
|
||||||
|
secp384r1 = 0x0018,
|
||||||
|
secp521r1 = 0x0019,
|
||||||
|
x25519 = 0x001D,
|
||||||
|
x448 = 0x001E,
|
||||||
|
|
||||||
|
/* Finite Field Groups (DHE) */
|
||||||
|
ffdhe2048 = 0x0100,
|
||||||
|
ffdhe3072 = 0x0101,
|
||||||
|
ffdhe4096 = 0x0102,
|
||||||
|
ffdhe6144 = 0x0103,
|
||||||
|
ffdhe8192 = 0x0104,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct NamedGroupList {
|
||||||
|
length: u16,
|
||||||
|
named_group_list: Vec<NamedGroup>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NamedGroupList {
|
||||||
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
|
usize::try_from(self.length).unwrap() + 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct KeyShareEntry {
|
||||||
|
group: NamedGroup,
|
||||||
|
length: u16,
|
||||||
|
key_exchange: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyShareEntry {
|
||||||
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
|
2 + 2 + usize::try_from(self.length).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) enum KeyShareEntryContent {
|
||||||
|
KeyShareClientHello {
|
||||||
|
length: u16,
|
||||||
|
client_shares: Vec<KeyShareEntry>,
|
||||||
|
},
|
||||||
|
KeyShareHelloRetryRequest {
|
||||||
|
selected_group: NamedGroup,
|
||||||
|
},
|
||||||
|
KeyShareServerHello {
|
||||||
|
server_share: KeyShareEntry,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl KeyShareEntryContent {
|
||||||
|
pub(crate) fn get_length(&self) -> usize {
|
||||||
|
match self {
|
||||||
|
Self::KeyShareClientHello { length, client_shares } => 2 + usize::try_from(*length).unwrap(),
|
||||||
|
Self::KeyShareHelloRetryRequest { selected_group } => 2,
|
||||||
|
Self::KeyShareServerHello { server_share } => server_share.get_length(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub(crate) enum NameType {
|
||||||
|
host_name = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) enum ServerNameContent {
|
||||||
|
HostName {
|
||||||
|
length: u16,
|
||||||
|
host_name: Vec<u8>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct ServerName {
|
||||||
|
name_type: NameType,
|
||||||
|
name: ServerNameContent,
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue