1use hmac::digest::generic_array::{typenum::U32, GenericArray};
5use w5500_hl::Hostname;
6
7use crate::{
8 cipher_suites::CipherSuite, extension::ExtensionType, key_schedule::KeySchedule, ContentType,
9 TlsVersion,
10};
11use core::mem::size_of;
12use sha2::Sha256;
13
14use super::HandshakeType;
15
16macro_rules! const_concat_bytes {
17 ($a:expr, $b:expr $(,)*) => {{
18 const __LEN: usize = $a.len() + $b.len();
19 const __CONCATENATED: [u8; __LEN] = {
20 let mut out: [u8; __LEN] = [0u8; __LEN];
21 let mut i = 0;
22 while i < $a.len() {
23 out[i] = $a[i];
24 i += 1;
25 }
26 i = 0;
27 while i < $b.len() {
28 out[i + $a.len()] = $b[i];
29 i += 1;
30 }
31 out
32 };
33
34 __CONCATENATED
35 }};
36}
37
38#[repr(u16)]
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44#[non_exhaustive]
45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
46pub enum SignatureScheme {
47 RsaPkcs1Sha256 = 0x0401, RsaPkcs1Sha384 = 0x0501,
50 RsaPkcs1Sha512 = 0x0601,
51 EcdsaSecp256r1Sha256 = 0x0403, EcdsaSecp384r1Sha384 = 0x0503,
54 EcdsaSecp521r1Sha512 = 0x0603,
55 RsaPssRsaeSha256 = 0x0804, RsaPssRsaeSha384 = 0x0805,
58 RsaPssRsaeSha512 = 0x0806,
59 Ed25519 = 0x0807,
61 Ed448 = 0x0808,
62 RsaPssPssSha256 = 0x0809,
64 RsaPssPssSha384 = 0x080a,
65 RsaPssPssSha512 = 0x080b,
66 RsaPkcs1Sha1 = 0x0201,
68 EcdsaSha1 = 0x0203,
69 }
72
73impl From<SignatureScheme> for u16 {
74 #[inline]
75 fn from(signature_scheme: SignatureScheme) -> Self {
76 signature_scheme as u16
77 }
78}
79
80impl TryFrom<u16> for SignatureScheme {
81 type Error = u16;
82
83 fn try_from(value: u16) -> Result<Self, Self::Error> {
84 match value {
85 x if x == (Self::RsaPkcs1Sha256 as u16) => Ok(Self::RsaPkcs1Sha256),
86 x if x == (Self::RsaPkcs1Sha384 as u16) => Ok(Self::RsaPkcs1Sha384),
87 x if x == (Self::RsaPkcs1Sha512 as u16) => Ok(Self::RsaPkcs1Sha512),
88 x if x == (Self::EcdsaSecp256r1Sha256 as u16) => Ok(Self::EcdsaSecp256r1Sha256),
89 x if x == (Self::EcdsaSecp384r1Sha384 as u16) => Ok(Self::EcdsaSecp384r1Sha384),
90 x if x == (Self::EcdsaSecp521r1Sha512 as u16) => Ok(Self::EcdsaSecp521r1Sha512),
91 x if x == (Self::RsaPssRsaeSha256 as u16) => Ok(Self::RsaPssRsaeSha256),
92 x if x == (Self::RsaPssRsaeSha384 as u16) => Ok(Self::RsaPssRsaeSha384),
93 x if x == (Self::RsaPssRsaeSha512 as u16) => Ok(Self::RsaPssRsaeSha512),
94 x if x == (Self::Ed25519 as u16) => Ok(Self::Ed25519),
95 x if x == (Self::Ed448 as u16) => Ok(Self::Ed448),
96 x if x == (Self::RsaPssPssSha256 as u16) => Ok(Self::RsaPssPssSha256),
97 x if x == (Self::RsaPssPssSha384 as u16) => Ok(Self::RsaPssPssSha384),
98 x if x == (Self::RsaPssPssSha512 as u16) => Ok(Self::RsaPssPssSha512),
99 x if x == (Self::RsaPkcs1Sha1 as u16) => Ok(Self::RsaPkcs1Sha1),
100 x if x == (Self::EcdsaSha1 as u16) => Ok(Self::EcdsaSha1),
101 x => Err(x),
102 }
103 }
104}
105
106#[repr(u8)]
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
111pub(crate) enum NameType {
112 Hostname = 0,
113}
114
115#[repr(u16)]
120#[non_exhaustive]
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122#[allow(non_camel_case_types, dead_code)]
123#[cfg_attr(feature = "defmt", derive(defmt::Format))]
124pub(crate) enum NamedGroup {
125 secp256r1 = 0x0017, secp384r1 = 0x0018,
128 secp521r1 = 0x0019,
129 x25519 = 0x001D,
130 x448 = 0x001E,
131 ffdhe2048 = 0x0100,
133 ffdhe3072 = 0x0101,
134 ffdhe4096 = 0x0102,
135 ffdhe6144 = 0x0103,
136 ffdhe8192 = 0x0104,
137 }
141
142impl NamedGroup {
143 pub const fn msb(self) -> u8 {
144 ((self as u16) >> 8) as u8
145 }
146
147 pub const fn lsb(self) -> u8 {
148 self as u8
149 }
150}
151
152impl TryFrom<u16> for NamedGroup {
153 type Error = u16;
154
155 fn try_from(value: u16) -> Result<Self, Self::Error> {
156 match value {
157 x if x == (Self::secp256r1 as u16) => Ok(Self::secp256r1),
158 x if x == (Self::secp384r1 as u16) => Ok(Self::secp384r1),
159 x if x == (Self::secp521r1 as u16) => Ok(Self::secp521r1),
160 x if x == (Self::x25519 as u16) => Ok(Self::x25519),
161 x if x == (Self::x448 as u16) => Ok(Self::x448),
162 x if x == (Self::ffdhe2048 as u16) => Ok(Self::ffdhe2048),
163 x if x == (Self::ffdhe3072 as u16) => Ok(Self::ffdhe3072),
164 x if x == (Self::ffdhe4096 as u16) => Ok(Self::ffdhe4096),
165 x if x == (Self::ffdhe6144 as u16) => Ok(Self::ffdhe6144),
166 x if x == (Self::ffdhe8192 as u16) => Ok(Self::ffdhe8192),
167 x => Err(x),
168 }
169 }
170}
171
172#[repr(u8)]
176#[non_exhaustive]
177#[derive(Debug, Clone, Copy, PartialEq, Eq)]
178#[allow(dead_code)]
179#[cfg_attr(feature = "defmt", derive(defmt::Format))]
180pub(crate) enum PskKeyExchangeMode {
181 Ke = 0,
185 DheKe = 1,
192}
193
194const fn vector_u8<const NUM_ELEMENTS: usize, const ELEMENT_SIZE: usize, const N: usize>(
197 values: [[u8; ELEMENT_SIZE]; NUM_ELEMENTS],
198) -> [u8; N] {
199 let mut ret: [u8; N] = [0; N];
200
201 let length: usize = ELEMENT_SIZE * NUM_ELEMENTS;
202
203 ret[0] = length as u8;
205
206 let mut value_idx: usize = 0;
208 while value_idx < NUM_ELEMENTS {
209 let mut value_byte_idx: usize = 0;
210 while value_byte_idx < ELEMENT_SIZE {
211 ret[value_idx * ELEMENT_SIZE + value_byte_idx + size_of::<u8>()] =
212 values[value_idx][value_byte_idx];
213 value_byte_idx += 1;
214 }
215 value_idx += 1;
216 }
217
218 ret
219}
220
221const fn vector_u16<const NUM_ELEMENTS: usize, const ELEMENT_SIZE: usize, const N: usize>(
224 values: [[u8; ELEMENT_SIZE]; NUM_ELEMENTS],
225) -> [u8; N] {
226 let mut ret: [u8; N] = [0; N];
227
228 let length: usize = ELEMENT_SIZE * NUM_ELEMENTS;
229 let length: u16 = length as u16;
230
231 let mut length_idx: usize = 0;
232 while length_idx < size_of::<u16>() {
233 ret[length_idx] = length.to_be_bytes()[length_idx];
234 length_idx += 1;
235 }
236
237 let mut value_idx: usize = 0;
239 while value_idx < NUM_ELEMENTS {
240 let mut value_byte_idx: usize = 0;
241 while value_byte_idx < ELEMENT_SIZE {
242 ret[value_idx * ELEMENT_SIZE + value_byte_idx + size_of::<u16>()] =
243 values[value_idx][value_byte_idx];
244 value_byte_idx += 1;
245 }
246 value_idx += 1;
247 }
248
249 ret
250}
251
252const fn supported_versions<const NUM_VERSIONS: usize, const N: usize>(
271 versions: [u16; NUM_VERSIONS],
272) -> [u8; N] {
273 let mut versions_bytes: [[u8; 2]; NUM_VERSIONS] = [[0; 2]; NUM_VERSIONS];
274 let mut version_idx: usize = 0;
275 while version_idx < NUM_VERSIONS {
276 versions_bytes[version_idx] = versions[version_idx].to_be_bytes();
277 version_idx += 1;
278 }
279 vector_u8(versions_bytes)
280}
281
282const fn psk_key_exchange_modes<const NUM_MODES: usize, const N: usize>(
295 modes: [PskKeyExchangeMode; NUM_MODES],
296) -> [u8; N] {
297 let mut mode_bytes: [[u8; 1]; NUM_MODES] = [[0; 1]; NUM_MODES];
298 let mut mode_idx: usize = 0;
299 while mode_idx < NUM_MODES {
300 mode_bytes[mode_idx][0] = modes[mode_idx] as u8;
301 mode_idx += 1;
302 }
303 vector_u8(mode_bytes)
304}
305
306const fn signature_scheme_list<const NUM_SCHEMES: usize, const N: usize>(
319 schemes: [SignatureScheme; NUM_SCHEMES],
320) -> [u8; N] {
321 let mut schemes_bytes: [[u8; 2]; NUM_SCHEMES] = [[0; 2]; NUM_SCHEMES];
322 let mut scheme_idx: usize = 0;
323 while scheme_idx < NUM_SCHEMES {
324 schemes_bytes[scheme_idx] = (schemes[scheme_idx] as u16).to_be_bytes();
325 scheme_idx += 1;
326 }
327 vector_u16(schemes_bytes)
328}
329
330const fn named_group_list<const N_VALUES: usize, const N: usize>(
343 values: [NamedGroup; N_VALUES],
344) -> [u8; N] {
345 let mut value_bytes: [[u8; 2]; N_VALUES] = [[0; 2]; N_VALUES];
346 let mut value_idx: usize = 0;
347 while value_idx < N_VALUES {
348 value_bytes[value_idx] = (values[value_idx] as u16).to_be_bytes();
349 value_idx += 1;
350 }
351 vector_u16(value_bytes)
352}
353
354const fn extension<const DATA_LEN: usize, const N: usize>(
368 extension: ExtensionType,
369 data: [u8; DATA_LEN],
370) -> [u8; N] {
371 let mut ret: [u8; N] = [0; N];
372 ret[0] = (extension as u16).to_be_bytes()[0];
373 ret[1] = (extension as u16).to_be_bytes()[1];
374 ret[2] = (data.len() as u16).to_be_bytes()[0];
375 ret[3] = (data.len() as u16).to_be_bytes()[1];
376
377 let mut data_idx: usize = 0;
378 while data_idx < DATA_LEN {
379 ret[data_idx + 4] = data[data_idx];
380 data_idx += 1;
381 }
382
383 ret
384}
385
386const fn cipher_suites<const N_VALUES: usize, const N: usize>(
406 values: [CipherSuite; N_VALUES],
407) -> [u8; N] {
408 let mut value_bytes: [[u8; 2]; N_VALUES] = [[0; 2]; N_VALUES];
409 let mut value_idx: usize = 0;
410 while value_idx < N_VALUES {
411 value_bytes[value_idx] = values[value_idx].value();
412 value_idx += 1;
413 }
414 vector_u16(value_bytes)
415}
416
417const CONTENT_TYPE: [u8; 1] = [ContentType::Handshake as u8];
418const TLS_VERSION: [u8; 2] = (TlsVersion::V1_2 as u16).to_be_bytes();
419
420pub const RECORD_HEADER_NO_LENGTH: [u8; CONTENT_TYPE.len() + TLS_VERSION.len()] =
421 const_concat_bytes!(CONTENT_TYPE, TLS_VERSION);
422
423const LEGACY_SESION_ID_LENGTH: [u8; 1] = [0];
424
425const CIPHER_SUITES: [CipherSuite; 1] = [CipherSuite::TLS_AES_128_GCM_SHA256];
426const CIPHER_SUITES_LIST: [u8; CIPHER_SUITES.len() * size_of::<u16>() + size_of::<u16>()] =
427 cipher_suites(CIPHER_SUITES);
428
429const LEGACY_COMPRESSION_METHODS: [u8; 2] = [1, 0];
431
432pub const LEGACY_THINGS_AND_CIPHER_SUITES: [u8; LEGACY_SESION_ID_LENGTH.len()
433 + CIPHER_SUITES_LIST.len()
434 + LEGACY_COMPRESSION_METHODS.len()] = const_concat_bytes!(
435 const_concat_bytes!(LEGACY_SESION_ID_LENGTH, CIPHER_SUITES_LIST),
436 LEGACY_COMPRESSION_METHODS
437);
438
439const SUPPORTED_VERSIONS: [u16; 1] = [TlsVersion::V1_3 as u16];
440const CLIENT_HELLO_SUPPORTED_VERSIONS: [u8; SUPPORTED_VERSIONS.len() * size_of::<u16>()
441 + size_of::<u8>()] = supported_versions(SUPPORTED_VERSIONS);
442const CLIENT_HELLO_SUPPORTED_VERSIONS_EXTENSION: [u8; CLIENT_HELLO_SUPPORTED_VERSIONS.len()
443 + size_of::<u16>()
444 + size_of::<u16>()] = extension(
445 ExtensionType::SupportedVersions,
446 CLIENT_HELLO_SUPPORTED_VERSIONS,
447);
448
449const SIGNATURE_SCHEMES: [SignatureScheme; 9] = [
450 SignatureScheme::RsaPkcs1Sha256,
451 SignatureScheme::RsaPkcs1Sha384,
452 SignatureScheme::RsaPkcs1Sha512,
453 SignatureScheme::EcdsaSecp256r1Sha256,
454 SignatureScheme::EcdsaSecp384r1Sha384,
455 SignatureScheme::RsaPssRsaeSha256,
456 SignatureScheme::RsaPssRsaeSha384,
457 SignatureScheme::RsaPssRsaeSha512,
458 SignatureScheme::Ed25519,
459];
460const SIGNATURE_SCHEME_LIST: [u8; SIGNATURE_SCHEMES.len() * size_of::<u16>() + size_of::<u16>()] =
461 signature_scheme_list(SIGNATURE_SCHEMES);
462const SIGNATURE_ALGORITHMS_EXTENSION: [u8; SIGNATURE_SCHEME_LIST.len()
463 + size_of::<u16>()
464 + size_of::<u16>()] = extension(ExtensionType::SignatureAlgorithms, SIGNATURE_SCHEME_LIST);
465
466const SUPPORTED_GROUPS: [NamedGroup; 1] = [NamedGroup::secp256r1];
467const NAMED_GROUP_LIST: [u8; SUPPORTED_GROUPS.len() * size_of::<u16>() + size_of::<u16>()] =
468 named_group_list(SUPPORTED_GROUPS);
469const SUPPORTED_GROUPS_EXTENSION: [u8; NAMED_GROUP_LIST.len()
470 + size_of::<u16>()
471 + size_of::<u16>()] = extension(ExtensionType::SupportedGroups, NAMED_GROUP_LIST);
472
473const KEY_EXCHANGE_MODES: [PskKeyExchangeMode; 1] = [PskKeyExchangeMode::DheKe];
474const KEY_EXCHANGE_MODES_LIST: [u8; KEY_EXCHANGE_MODES.len() + size_of::<u8>()] =
475 psk_key_exchange_modes(KEY_EXCHANGE_MODES);
476const KEY_EXCHANGE_MODES_EXTENSION: [u8; KEY_EXCHANGE_MODES_LIST.len()
477 + size_of::<u16>()
478 + size_of::<u16>()] = extension(ExtensionType::PskKeyExchangeModes, KEY_EXCHANGE_MODES_LIST);
479
480pub const CONST_EXTENSIONS: [u8; SUPPORTED_GROUPS_EXTENSION.len()
481 + KEY_EXCHANGE_MODES_EXTENSION.len()
482 + CLIENT_HELLO_SUPPORTED_VERSIONS_EXTENSION.len()
483 + SIGNATURE_ALGORITHMS_EXTENSION.len()] = const_concat_bytes!(
484 const_concat_bytes!(SUPPORTED_GROUPS_EXTENSION, KEY_EXCHANGE_MODES_EXTENSION),
485 const_concat_bytes!(
486 CLIENT_HELLO_SUPPORTED_VERSIONS_EXTENSION,
487 SIGNATURE_ALGORITHMS_EXTENSION
488 ),
489);
490
491struct ClientHelloWriter<'a> {
492 buf: &'a mut [u8],
493 len: usize,
494 key_schedule: &'a mut KeySchedule,
495}
496
497impl<'a> ClientHelloWriter<'a> {
498 pub fn copy_from_slice(&mut self, src: &[u8]) {
499 self.copy_from_slice_no_hash(src);
500 self.key_schedule.update_transcript_hash(src);
501 }
502
503 pub fn copy_from_slice_no_hash(&mut self, src: &[u8]) {
504 self.buf[self.len..(self.len + src.len())].copy_from_slice(src);
505 self.len += src.len();
506 }
507
508 pub fn push(&mut self, byte: u8) {
509 self.buf[self.len] = byte;
510 self.key_schedule.update_transcript_hash(&[byte]);
511 self.len += 1;
512 }
513
514 pub fn write_binder(&mut self, psk: &[u8], truncated_transcript_hash: Sha256) {
515 let binder: GenericArray<u8, U32> =
516 self.key_schedule.binder(psk, truncated_transcript_hash);
517 self.copy_from_slice(&binder);
518 }
519}
520
521#[allow(clippy::too_many_arguments)]
522pub fn ser(
523 buf: &mut [u8],
524 random: &[u8; 32],
525 hostname: &Hostname,
526 client_public_key: &[u8; 65],
527 key_schedule: &mut KeySchedule,
528 psk: &[u8],
529 identity: &[u8],
530 record_size_limit: u16,
531) -> usize {
532 let mut writer: ClientHelloWriter = ClientHelloWriter {
533 buf,
534 len: 0,
535 key_schedule,
536 };
537
538 let extensions_length: u16 =
539 137 + (CONST_EXTENSIONS.len() as u16) + u16::from(hostname.len()) + (identity.len() as u16);
540 let handshake_length: u16 = 43 + extensions_length;
541 let tls_plaintext_length: u16 = 4 + handshake_length;
542
543 writer.copy_from_slice_no_hash(&RECORD_HEADER_NO_LENGTH);
545 writer.copy_from_slice_no_hash(&tls_plaintext_length.to_be_bytes());
546 let start_of_record: usize = writer.len;
547
548 writer.push(HandshakeType::ClientHello as u8);
549 writer.push(0);
550 writer.copy_from_slice(&handshake_length.to_be_bytes());
551 let start_of_handshake: usize = writer.len;
552
553 writer.copy_from_slice(&u16::from(TlsVersion::V1_2).to_be_bytes());
554 writer.copy_from_slice(random);
555 writer.copy_from_slice(&LEGACY_THINGS_AND_CIPHER_SUITES);
556 writer.copy_from_slice(&extensions_length.to_be_bytes());
557 let start_of_extensions: usize = writer.len;
558
559 writer.copy_from_slice(&CONST_EXTENSIONS);
560
561 {
564 let hostname_len: u16 = hostname.len().into();
565 let server_name_list_len: u16 = hostname_len + 3;
566 let extension_len: u16 = server_name_list_len + 2;
567
568 writer.copy_from_slice(&u16::from(ExtensionType::ServerName).to_be_bytes());
569 writer.copy_from_slice(&extension_len.to_be_bytes());
570 writer.copy_from_slice(&server_name_list_len.to_be_bytes());
571 writer.push(NameType::Hostname as u8);
572 writer.copy_from_slice(&hostname_len.to_be_bytes());
573 writer.copy_from_slice(hostname.as_bytes());
574 }
575
576 {
579 const P256_UNCOMPRESSED_POINT_SIZE: u16 = 65;
580 const CLIENT_SHARES_LEN: u16 = P256_UNCOMPRESSED_POINT_SIZE
581 + (size_of::<u16>() as u16)
582 + (size_of::<NamedGroup>() as u16);
583 const EXTENSION_LEN: u16 = CLIENT_SHARES_LEN + (size_of::<u16>() as u16);
584
585 const KEY_SHARE_EXTENSION_HEADER: [u8; 10] = [
586 ExtensionType::KeyShare.msb(),
587 ExtensionType::KeyShare.lsb(),
588 (EXTENSION_LEN >> 8) as u8,
589 EXTENSION_LEN as u8,
590 (CLIENT_SHARES_LEN >> 8) as u8,
591 CLIENT_SHARES_LEN as u8,
592 NamedGroup::secp256r1.msb(),
593 NamedGroup::secp256r1.lsb(),
594 (P256_UNCOMPRESSED_POINT_SIZE >> 8) as u8,
595 P256_UNCOMPRESSED_POINT_SIZE as u8,
596 ];
597 writer.copy_from_slice(&KEY_SHARE_EXTENSION_HEADER);
598 writer.copy_from_slice(client_public_key);
599 }
600
601 {
604 writer.copy_from_slice(&u16::from(ExtensionType::RecordSizeLimit).to_be_bytes());
605 writer.copy_from_slice(&2_u16.to_be_bytes());
606 writer.copy_from_slice(&record_size_limit.to_be_bytes());
607 }
608
609 let len: usize = {
612 let identity_len: u16 = identity.len() as u16;
613 let identities_len: u16 =
614 (identity_len + (size_of::<u32>() as u16)) + (size_of::<u16>() as u16);
615 const BINDER_LEN: u8 = 32;
616 const BINDERS_LEN: u16 = (BINDER_LEN as u16) + (size_of::<u8>() as u16);
617 let extension_len: u16 =
618 identities_len + BINDERS_LEN + (size_of::<u16>() as u16) + (size_of::<u16>() as u16);
619
620 const OBFUSCATED_TICKET_AGE: u32 = 0;
623
624 writer.copy_from_slice(&u16::from(ExtensionType::PreSharedKey).to_be_bytes());
625 writer.copy_from_slice(&extension_len.to_be_bytes());
626 writer.copy_from_slice(&identities_len.to_be_bytes());
627 writer.copy_from_slice(&identity_len.to_be_bytes());
628 writer.copy_from_slice(identity);
629 writer.copy_from_slice(&OBFUSCATED_TICKET_AGE.to_be_bytes());
630 let truncated_transcript_hash: Sha256 = writer.key_schedule.transcript_hash();
631 writer.copy_from_slice(&BINDERS_LEN.to_be_bytes());
632 writer.copy_from_slice(&[BINDER_LEN]);
633 writer.write_binder(psk, truncated_transcript_hash);
634 writer.len
635 };
636
637 let actual_extensions_length: u16 = (len - start_of_extensions) as u16;
638 assert_eq!(actual_extensions_length, extensions_length);
639
640 let actual_handshake_length: u16 = (len - start_of_handshake) as u16;
641 assert_eq!(actual_handshake_length, handshake_length);
642
643 let actual_tls_plaintext_length: u16 = (len - start_of_record) as u16;
644 assert_eq!(actual_tls_plaintext_length, tls_plaintext_length);
645
646 len
647}