w5500_tls/
lib.rs

1//! TLS v1.3 client for the [Wiznet W5500] SPI internet offload chip.
2//!
3//! This requires roughly 19k of flash for a `thumbv7em-none-eabi` target
4//! with `-O3`, debug assertions enabled, and the `p256-cm4` feature.
5//! Enabling all logging requires an additional ~40k of flash.
6//!
7//! # Warning
8//!
9//! ⚠️ This is in an early alpha state ⚠️
10//!
11//! All the usual security disclaimers apply here, read the license, your hamster
12//! may explode if you use this, don't use this code in production, etc.
13//!
14//! Additionally this is not secure from side channel attacks.
15//!
16//! * Encryption may occur in-place in the socket buffers, anything with access
17//!   to the physical SPI bus or the SPI device registers can easily intercept
18//!   data.
19//! * To facilitate the ill-advised encryption in-place in the socket buffers
20//!   there is a hacky AES implementation that has little thought put towards
21//!   constant-time evaluation.
22//!
23//! # Limitations
24//!
25//! At the moment this only supports pre-shared keys.
26//! This will not work for majority of web (HTTPS) applications.
27//!
28//! * Requires a local buffer equal to the socket buffer size.
29//!   * TLS record fragmentation makes implementing socket buffer streaming
30//!     impractical.
31//! * Limited cryptography support
32//!   * Cipher: `TLS_AES_128_GCM_SHA256`
33//!   * Key Exchange: `secp256r1`
34//! * Does not support certificate validation
35//! * Does not support client certificates (mutual TLS)
36//! * Does not support early data
37//! * Does not support serving TLS
38//!
39//! # Feature Flags
40//!
41//! All features are disabled by default.
42//!
43//! * `eh0`: Passthrough to [`w5500-hl`].
44//! * `eh1`: Passthrough to [`w5500-hl`].
45//! * `defmt`: Enable logging with `defmt`. Also a passthrough to [`w5500-hl`].
46//! * `log`: Enable logging with `log`.
47//! * `p256-cm4`: Use [`p256-cm4`], a P256 implementation optimized for the
48//!   Cortex-M4 CPU.
49//!
50//! [`w5500-hl`]: https://crates.io/crates/w5500-hl
51//! [`p256-cm4`]: https://crates.io/crates/p256-cm4
52//! [Wiznet W5500]: https://www.wiznet.io/product-item/w5500/
53#![cfg_attr(docsrs, feature(doc_cfg), feature(doc_auto_cfg))]
54#![cfg_attr(not(test), no_std)]
55#![deny(unsafe_code)]
56#![warn(missing_docs)]
57
58// This mod MUST go first, so that the others see its macros.
59pub(crate) mod fmt;
60
61mod alert;
62mod cipher_suites;
63mod crypto;
64mod extension;
65mod handshake;
66mod io;
67mod key_schedule;
68mod record;
69
70use crate::crypto::p256::PublicKey;
71pub use alert::{Alert, AlertDescription, AlertLevel};
72use core::{cmp::min, convert::Infallible};
73use extension::ExtensionType;
74use handshake::{
75    client_hello::{self, NamedGroup},
76    HandshakeType,
77};
78use hl::{
79    io::{Read, Seek, Write},
80    ll::{BufferSize, Registers, Sn, SocketInterrupt, SocketInterruptMask},
81    net::SocketAddrV4,
82    Common, Error as HlError, Hostname, Tcp, TcpReader, TcpWriter,
83};
84use io::Buffer;
85pub use io::{TlsReader, TlsWriter};
86use key_schedule::KeySchedule;
87pub use rand_core;
88use rand_core::{CryptoRng, RngCore};
89use record::{ContentType, RecordHeader};
90use sha2::{
91    digest::{generic_array::GenericArray, typenum::U32},
92    Sha256,
93};
94pub use w5500_hl as hl;
95pub use w5500_hl::ll;
96
97const GCM_TAG_LEN: usize = 16;
98
99#[repr(u16)]
100enum TlsVersion {
101    V1_2 = 0x0303,
102    V1_3 = 0x0304,
103}
104
105impl From<TlsVersion> for u16 {
106    #[inline]
107    fn from(tls_version: TlsVersion) -> Self {
108        tls_version as u16
109    }
110}
111
112impl TlsVersion {
113    pub const fn msb(self) -> u8 {
114        ((self as u16) >> 8) as u8
115    }
116
117    pub const fn lsb(self) -> u8 {
118        self as u8
119    }
120}
121
122/// TLS errors.
123///
124/// When an error occurs the connection is either reset or disconnecting.
125///
126/// After the connection has disconnected the next call to [`Client::process`]
127/// will create a new connection.
128#[derive(Debug, Clone, Copy, PartialEq, Eq)]
129#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130pub enum Error {
131    /// Alert sent from the server.
132    Server(Alert),
133    /// Alert sent by the client.
134    Client(Alert),
135    /// Unexpected TCP disconnection.
136    UnexpectedDisconnect,
137    /// TCP connection timeout.
138    TcpTimeout,
139    /// A timeout occurred while waiting for the client to transition from this
140    /// state.
141    StateTimeout(State),
142    /// Tried to write with [`Client::writer`] or [`Client::write_all`] before
143    /// the handshake has completed.
144    NotConnected,
145}
146
147/// Duration in seconds to wait for the TLS server to send a response.
148const TIMEOUT_SECS: u32 = 10;
149
150/// Internal TLS client states.
151// https://datatracker.ietf.org/doc/html/rfc8446#appendix-A.1
152#[derive(Debug, PartialEq, Eq, Clone, Copy)]
153#[cfg_attr(feature = "defmt", derive(defmt::Format))]
154pub enum State {
155    /// Reset and idle.
156    Reset,
157    /// TCP handshake started, waiting for the CON int.
158    WaitConInt,
159    /// Sent ClientHello, waiting for ServerHello.
160    WaitServerHello,
161    /// Received ServerHello, waiting for EncryptedExtensions.
162    WaitEncryptedExtensions,
163    /// Received EncryptedExtensions, waiting for ServerFinished.
164    WaitFinished,
165    /// Client will send ClientFinished on the next call to [`Client::process`].
166    SendFinished,
167    /// Sent ClientFinished, TLS handshake has completed.
168    Connected,
169    /// The client sent an alert, waiting for the SENDOK interrupt before
170    /// starting a TCP disconnection.
171    WaitAlertSendOk,
172    /// Client will start a TCP disconnection on the next call to
173    /// [`Client::process`].
174    SendDiscon,
175    /// Client started a TCP disconnection, waiting for the DISCON interrupt.
176    WaitDiscon,
177}
178
179/// TLS events.
180///
181/// These are events that need to be handled externally by your firmware,
182/// such as new application data.
183///
184/// This is returned by [`Client::process`].
185#[derive(Debug, PartialEq, Eq)]
186#[cfg_attr(feature = "defmt", derive(defmt::Format))]
187pub enum Event {
188    /// A hint to call [`Client::process`] after this many seconds have elapsed.
189    ///
190    /// This is just a hint and does not have to be used.
191    ///
192    /// The inner value may increase or decreases with successive calls to
193    /// [`Client::process`].
194    ///
195    /// This is used for state timeout tracking.
196    CallAfter(u32),
197    /// New application data was received.
198    ///
199    /// Calling [`Client::reader`] will return a [`TlsReader`] to read the
200    /// data.
201    ApplicationData,
202    /// The handshake finished, and you can read and write application data.
203    HandshakeFinished,
204    /// Expected disconnection.
205    Disconnect,
206    /// No event occurred, the client ready and idle.
207    None,
208}
209
210/// TLS Client.
211///
212/// # RX Buffer
213///
214/// The generic `N` is the size of the RX buffer, this must be set to a valid
215/// socket [`BufferSize`].
216///
217/// This buffer must be large enough to contain the largest handshake fragment.
218/// The socket RX buffer size will be set to match N.
219/// When using pre-shared keys the default value of `N=2048` is typically
220/// sufficient.
221///
222/// This buffer is necessary because handshakes may be fragmented across
223/// multiple records, and due to the gaps left by the headers and footers is is
224/// not feasible to reassemble fragments within the socket buffers.
225pub struct Client<'hn, 'psk, 'b, const N: usize> {
226    sn: Sn,
227    src_port: u16,
228    hostname: Hostname<'hn>,
229    dst: SocketAddrV4,
230    state: State,
231
232    /// Timeout for TLS server responses
233    timeout: Option<u32>,
234    key_schedule: KeySchedule,
235
236    identity: &'psk [u8],
237    psk: &'psk [u8],
238
239    // RX buffer
240    rx: Buffer<'b, N>,
241}
242
243const fn size_to_buffersize(size: usize) -> BufferSize {
244    match size {
245        1024 => BufferSize::KB1,
246        2048 => BufferSize::KB2,
247        4096 => BufferSize::KB4,
248        8192 => BufferSize::KB8,
249        16384 => BufferSize::KB16,
250        _ => ::core::panic!("valid buffer sizes are 1024, 2048, 4096, 8192, or 16384"),
251    }
252}
253
254impl<'hn, 'psk, 'b, const N: usize> Client<'hn, 'psk, 'b, N> {
255    const RX_BUFFER_SIZE: BufferSize = size_to_buffersize(N);
256
257    // maximum plaintext size
258    // https://www.rfc-editor.org/rfc/rfc8449
259    // minus 1 because the local memory circular buffer implementation
260    // does not use full/empty flags
261    const RECORD_SIZE_LIMIT: u16 =
262        (N as u16) - (GCM_TAG_LEN as u16) - (RecordHeader::LEN as u16) - 1;
263
264    /// Create a new TLS client.
265    ///
266    /// You must resolve the hostname to an [`Ipv4Addr`] externally.
267    ///
268    /// # Arguments
269    ///
270    /// * `sn` Socket number for the TLS client.
271    /// * `src_port` Source port, use any unused port.
272    /// * `hostname` Server hostname.
273    /// * `dst` Server address.
274    /// * `identity` PSK identity
275    /// * `psk` pre-shared key
276    /// * `rx` RX buffer, this must be 1024, 2048, 4096, 8192, or 16384 bytes
277    ///   in length
278    ///
279    /// # Example
280    ///
281    /// ```
282    /// # const MY_KEY: [u8; 1] = [0];
283    /// use w5500_tls::{
284    ///     Client,
285    ///     {
286    ///         hl::Hostname,
287    ///         ll::{
288    ///             net::{Ipv4Addr, SocketAddrV4},
289    ///             Sn,
290    ///         },
291    ///     },
292    /// };
293    ///
294    /// static mut RX: [u8; 2048] = [0; 2048];
295    ///
296    /// const DST: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 4), 8883);
297    /// const HOSTNAME: Hostname = Hostname::new_unwrapped("server.local");
298    /// const SRC_PORT: u16 = 1234;
299    /// const TLS_SN: Sn = Sn::Sn4;
300    ///
301    /// let tls_client: Client<2048> = Client::new(
302    ///     TLS_SN,
303    ///     SRC_PORT,
304    ///     HOSTNAME,
305    ///     DST,
306    ///     b"mykeyidentity",
307    ///     &MY_KEY,
308    ///     unsafe { &mut RX },
309    /// );
310    /// ```
311    ///
312    /// [`Ipv4Addr`]: w5500_hl::ll::net::Ipv4Addr
313    pub fn new(
314        sn: Sn,
315        src_port: u16,
316        hostname: Hostname<'hn>,
317        dst: SocketAddrV4,
318        identity: &'psk [u8],
319        psk: &'psk [u8],
320        rx: &'b mut [u8; N],
321    ) -> Self {
322        Self {
323            sn,
324            src_port,
325            hostname,
326            dst,
327            state: State::Reset,
328            timeout: None,
329            key_schedule: KeySchedule::default(),
330            identity,
331            psk,
332            rx: Buffer::from(rx),
333        }
334    }
335
336    fn timeout_elapsed_secs(&self, monotonic_secs: u32) -> Option<u32> {
337        self.timeout.map(|to| monotonic_secs - to)
338    }
339
340    fn set_state_with_timeout(&mut self, state: State, monotonic_secs: u32) -> u32 {
341        debug!(
342            "{:?} -> {:?} with timeout {}",
343            self.state, state, monotonic_secs
344        );
345        self.state = state;
346        self.timeout = Some(monotonic_secs);
347        TIMEOUT_SECS
348    }
349
350    fn set_state(&mut self, state: State) {
351        debug!("{:?} -> {:?} without timeout", self.state, state);
352        self.state = state;
353        self.timeout = None;
354    }
355
356    fn set_state_send_discon(&mut self, monotonic_secs: u32) -> u32 {
357        self.key_schedule.reset();
358        self.set_state_with_timeout(State::SendDiscon, monotonic_secs)
359    }
360
361    fn reset(&mut self) {
362        self.key_schedule.reset();
363        self.set_state(State::Reset);
364    }
365
366    /// Process the MQTT client.
367    ///
368    /// This should be called repeatedly until it returns:
369    ///
370    /// * `Err(_)` What to do upon errors is up to you.
371    /// * `Ok(Event::CallAfter(seconds))` Call this method again after the number
372    ///   of seconds indicated.
373    /// * `Ok(Event::None)` The client is idle; you can call [`writer`](Self::writer).
374    ///
375    /// This should also be called when there is a pending socket interrupt.
376    ///
377    /// # Arguments
378    ///
379    /// * `w5500` W5500 device implementing the [`Registers`] trait.
380    /// * `rng` secure random number generator.
381    ///   This is assumed to be infallible.
382    ///   If you have a fallible secure hardware RNG you can use that to seed
383    ///   an infallible software RNG.
384    /// * `monotonic_secs` Monotonically increasing (never decreasing) seconds
385    ///   since an epoch (typically system boot).
386    pub fn process<W5500: Registers, R: RngCore + CryptoRng>(
387        &mut self,
388        w5500: &mut W5500,
389        rng: &mut R,
390        monotonic_secs: u32,
391    ) -> Result<Event, Error> {
392        let sn_ir: SocketInterrupt = w5500.sn_ir(self.sn).unwrap_or_default();
393
394        if sn_ir.any_raised() {
395            if w5500.set_sn_ir(self.sn, sn_ir).is_err() {
396                return Err(self.send_fatal_alert(
397                    w5500,
398                    AlertDescription::InternalError,
399                    monotonic_secs,
400                ));
401            }
402
403            if sn_ir.con_raised() {
404                info!("CONN interrupt");
405                if let Err(e) = self.send_client_hello(w5500, rng, monotonic_secs) {
406                    return Err(self.send_fatal_alert(w5500, e, monotonic_secs));
407                }
408            }
409            if sn_ir.discon_raised() {
410                info!("DISCON interrupt");
411                // TODO: try to get discon reason from server
412                if self.state != State::WaitDiscon {
413                    warn!("Unexpected TCP disconnect");
414                    self.reset();
415                    return Ok(Event::Disconnect);
416                } else {
417                    return Err(Error::UnexpectedDisconnect);
418                }
419            }
420            if sn_ir.recv_raised() {
421                info!("RECV interrupt");
422            }
423            if sn_ir.timeout_raised() {
424                info!("TIMEOUT interrupt");
425                self.reset();
426                return Err(Error::TcpTimeout);
427            }
428            if sn_ir.sendok_raised() {
429                info!("SENDOK interrupt");
430                if self.state == State::WaitAlertSendOk {
431                    return Ok(Event::CallAfter(self.set_state_send_discon(monotonic_secs)));
432                }
433            }
434        }
435
436        match self.state {
437            State::Reset => {
438                match self.tcp_connect(w5500, monotonic_secs) {
439                    Ok(after) => return Ok(Event::CallAfter(after)),
440                    Err(e) => return Err(self.send_fatal_alert(w5500, e, monotonic_secs)),
441                };
442            }
443            State::SendDiscon => {
444                if w5500.tcp_disconnect(self.sn).is_err() {
445                    return Err(self.send_fatal_alert(
446                        w5500,
447                        AlertDescription::InternalError,
448                        monotonic_secs,
449                    ));
450                }
451                let after: u32 = self.set_state_with_timeout(State::WaitDiscon, monotonic_secs);
452                return Ok(Event::CallAfter(after));
453            }
454            _ => (),
455        }
456
457        // all incoming data must be ignored after sending an alert
458        if !matches!(self.state, State::WaitAlertSendOk | State::WaitDiscon) {
459            let sn_rx_rsr: u16 = match w5500.sn_rx_rsr(self.sn) {
460                Ok(sn_rx_rsr) => sn_rx_rsr,
461                Err(_) => {
462                    return Err(self.send_fatal_alert(
463                        w5500,
464                        AlertDescription::InternalError,
465                        monotonic_secs,
466                    ))
467                }
468            };
469            if sn_rx_rsr >= RecordHeader::LEN as u16 {
470                if let Some(event) = self.recv(w5500, monotonic_secs)? {
471                    return Ok(event);
472                }
473            }
474
475            if matches!(self.state, State::SendFinished) {
476                if let Err(e) = self.send_client_finished(w5500) {
477                    return Err(self.send_fatal_alert(w5500, e, monotonic_secs));
478                }
479                return Ok(Event::HandshakeFinished);
480            }
481        }
482
483        if let Some(elapsed_secs) = self.timeout_elapsed_secs(monotonic_secs) {
484            if elapsed_secs > TIMEOUT_SECS {
485                info!(
486                    "timeout waiting for state to transition from {:?}",
487                    self.state
488                );
489                let ret = Err(Error::StateTimeout(self.state));
490                if matches!(self.state, State::WaitDiscon) {
491                    self.reset()
492                } else {
493                    self.set_state(State::SendDiscon);
494                }
495                ret
496            } else {
497                let call_after: u32 = TIMEOUT_SECS.saturating_sub(elapsed_secs);
498                Ok(Event::CallAfter(call_after))
499            }
500        } else {
501            Ok(Event::None)
502        }
503    }
504
505    fn tcp_connect<W5500: Registers>(
506        &mut self,
507        w5500: &mut W5500,
508        monotonic_secs: u32,
509    ) -> Result<u32, AlertDescription> {
510        debug!("connecting to {}", self.dst);
511        w5500
512            .close(self.sn)
513            .map_err(|_| AlertDescription::InternalError)?;
514        w5500
515            .set_sn_rxbuf_size(self.sn, Self::RX_BUFFER_SIZE)
516            .map_err(|_| AlertDescription::InternalError)?;
517        let simr: u8 = w5500.simr().map_err(|_| AlertDescription::InternalError)?;
518        w5500
519            .set_simr(self.sn.bitmask() | simr)
520            .map_err(|_| AlertDescription::InternalError)?;
521        w5500
522            .set_sn_imr(self.sn, SocketInterruptMask::DEFAULT)
523            .map_err(|_| AlertDescription::InternalError)?;
524        w5500
525            .tcp_connect(self.sn, self.src_port, &self.dst)
526            .map_err(|_| AlertDescription::InternalError)?;
527        Ok(self.set_state_with_timeout(State::WaitConInt, monotonic_secs))
528    }
529
530    /// ```text
531    /// struct {
532    ///     ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
533    ///     Random random;
534    ///     opaque legacy_session_id<0..32>;
535    ///     CipherSuite cipher_suites<2..2^16-2>;
536    ///     opaque legacy_compression_methods<1..2^8-1>;
537    ///     Extension extensions<8..2^16-1>;
538    /// } ClientHello;
539    /// ```
540    fn send_client_hello<W5500: Registers, R: RngCore + CryptoRng>(
541        &mut self,
542        w5500: &mut W5500,
543        rng: &mut R,
544        monotonic_secs: u32,
545    ) -> Result<(), AlertDescription> {
546        self.rx.reset();
547
548        let mut random: [u8; 32] = [0; 32];
549        rng.fill_bytes(&mut random);
550
551        let client_public_key = self.key_schedule.new_client_secret(rng);
552
553        // using fragment buffer for TX since it is unused at this point
554        let len: usize = client_hello::ser(
555            self.rx.as_mut_buf(),
556            &random,
557            &self.hostname,
558            &client_public_key,
559            &mut self.key_schedule,
560            self.psk,
561            self.identity,
562            Self::RECORD_SIZE_LIMIT,
563        );
564        let buf: &[u8] = &self.rx.as_buf()[..len];
565
566        let mut writer: TcpWriter<W5500> = w5500
567            .tcp_writer(self.sn)
568            .map_err(|_| AlertDescription::InternalError)?;
569        writer
570            .write_all(buf)
571            .map_err(|_| AlertDescription::InternalError)?;
572        writer.send().map_err(|_| AlertDescription::InternalError)?;
573
574        self.key_schedule.increment_write_record_sequence_number();
575        self.set_state_with_timeout(State::WaitServerHello, monotonic_secs);
576        self.key_schedule.initialize_early_secret();
577
578        Ok(())
579    }
580
581    /// Send an alert to the server.
582    ///
583    /// # References
584    ///
585    /// * [RFC 8446 Appendix B.2](https://datatracker.ietf.org/doc/html/rfc8446#appendix-B.2)
586    ///
587    /// ```text
588    /// struct {
589    ///     AlertLevel level;
590    ///     AlertDescription description;
591    /// } Alert;
592    /// ```
593    fn send_alert<W5500: Registers>(
594        &mut self,
595        w5500: &mut W5500,
596        level: AlertLevel,
597        description: AlertDescription,
598        monotonic_secs: u32,
599    ) {
600        debug!("send_alert {:?} {:?}", level, description);
601
602        let mut try_send_alert = || -> Result<(), AlertDescription> {
603            if self.key_schedule.server_traffic_secret_exists() {
604                self.send_encrypted_record(
605                    w5500,
606                    ContentType::Alert,
607                    &[level.into(), description.into()],
608                )
609                .map_err(AlertDescription::map_w5500)?;
610            } else {
611                #[rustfmt::skip]
612                let buf: [u8; 7] = [
613                    ContentType::Alert.into(),
614                    TlsVersion::V1_2.msb(),
615                    TlsVersion::V1_2.lsb(),
616                    0, 2, // length
617                    level.into(),
618                    description.into(),
619                ];
620                let mut writer: TcpWriter<W5500> = w5500
621                    .tcp_writer(self.sn)
622                    .map_err(|_| AlertDescription::InternalError)?;
623                writer
624                    .write_all(&buf)
625                    .map_err(AlertDescription::map_w5500)?;
626                writer.send().map_err(|_| AlertDescription::InternalError)?;
627            }
628            Ok(())
629        };
630
631        let result: Result<(), AlertDescription> = try_send_alert();
632
633        self.key_schedule.reset();
634
635        if let Err(e1) = result {
636            error!("error while sending alert: {:?}", e1);
637            self.set_state_send_discon(monotonic_secs);
638        } else {
639            self.key_schedule.reset();
640            self.set_state_with_timeout(State::WaitAlertSendOk, monotonic_secs);
641        }
642    }
643
644    fn send_fatal_alert<W5500: Registers>(
645        &mut self,
646        w5500: &mut W5500,
647        description: AlertDescription,
648        monotonic_secs: u32,
649    ) -> Error {
650        self.send_alert(w5500, AlertLevel::Fatal, description, monotonic_secs);
651        Error::Client(Alert::new_fatal(description))
652    }
653
654    fn recv_change_cipher_spec(&mut self, header: &RecordHeader) -> Result<(), AlertDescription> {
655        if header.length() != 1 {
656            error!(
657                "expected length 1 for ChangeCipherSpec got {}",
658                header.length()
659            );
660            Err(AlertDescription::DecodeError)
661        } else {
662            let value: u8 = self.rx.pop_tail().ok_or(AlertDescription::DecodeError)?;
663
664            // https://datatracker.ietf.org/doc/html/rfc8446#section-5
665            // An implementation may receive an unencrypted record of type
666            // change_cipher_spec consisting of the single byte value 0x01 at any
667            // time after the first ClientHello message has been sent or received
668            // and before the peer's Finished message has been received and MUST
669            // simply drop it without further processing.
670            //
671            // An implementation which receives any other change_cipher_spec value or
672            // which receives a protected change_cipher_spec record MUST abort the
673            // handshake with an "unexpected_message" alert.
674            const REQUIRED_VALUE: u8 = 0x01;
675            if value != REQUIRED_VALUE {
676                error!(
677                    "change_cipher_spec value {:#02X} does not match expected value {:#02X}",
678                    value, REQUIRED_VALUE
679                );
680                Err(AlertDescription::UnexpectedMessage)
681            } else {
682                Ok(())
683            }
684        }
685    }
686
687    fn recv_header<W5500: Registers>(
688        &self,
689        w5500: &mut W5500,
690    ) -> Result<Option<RecordHeader>, AlertDescription> {
691        let mut header_buf: [u8; 5] = [0; 5];
692
693        let mut reader: TcpReader<W5500> = w5500
694            .tcp_reader(self.sn)
695            .map_err(AlertDescription::map_w5500)?;
696        reader
697            .read_exact(&mut header_buf)
698            .map_err(AlertDescription::map_w5500)?;
699
700        let header: RecordHeader = RecordHeader::deser(header_buf)?;
701        debug!("RecordHeader.length={}", header.length());
702
703        // The length MUST NOT exceed 2^14 bytes.
704        // An endpoint that receives a record that exceeds this length MUST
705        // terminate the connection with a "record_overflow" alert.
706        //
707        // We use the record size limit extension, so we can limit this to
708        // our RX buffer size
709        if header.length() > Self::RECORD_SIZE_LIMIT {
710            Err(AlertDescription::RecordOverflow)
711        } else if header.length().saturating_add(RecordHeader::LEN as u16) > reader.stream_len() {
712            Ok(None)
713        } else {
714            reader.done().map_err(|_| AlertDescription::InternalError)?;
715            Ok(Some(header))
716        }
717    }
718
719    fn recv_unencrypted_body<W5500: Registers>(
720        &mut self,
721        w5500: &mut W5500,
722        header: &RecordHeader,
723    ) -> Result<(), AlertDescription> {
724        let mut reader: TcpReader<W5500> = w5500
725            .tcp_reader(self.sn)
726            .map_err(AlertDescription::map_w5500)?;
727        let mut remain: usize = header.length().into();
728        let mut buf: [u8; 64] = [0; 64];
729        loop {
730            let read_len: usize = min(remain, buf.len());
731            if read_len == 0 {
732                break;
733            }
734            reader
735                .read_exact(&mut buf[..read_len])
736                .map_err(AlertDescription::map_w5500)?;
737            self.rx.extend_from_slice(&buf[..read_len])?;
738            remain -= read_len;
739        }
740
741        reader.done().map_err(|_| AlertDescription::InternalError)?;
742        Ok(())
743    }
744
745    fn recv<W5500: Registers>(
746        &mut self,
747        w5500: &mut W5500,
748        monotonic_secs: u32,
749    ) -> Result<Option<Event>, Error> {
750        let header: RecordHeader = match self.recv_header(w5500) {
751            Ok(Some(header)) => header,
752            Ok(None) => return Ok(None),
753            Err(e) => return Err(self.send_fatal_alert(w5500, e, monotonic_secs)),
754        };
755
756        let rx_buffer_contains_handshake_fragment: bool = self.rx.contains_handshake_fragment();
757
758        let actual_content_type: ContentType =
759            if matches!(header.content_type(), ContentType::ApplicationData) {
760                debug!("decrypting record");
761
762                let (key, nonce): ([u8; 16], [u8; 12]) =
763                    match self.key_schedule.server_key_and_nonce() {
764                        Some(x) => x,
765                        None => {
766                            error!("received ApplicationData before establishing keys");
767                            return Err(self.send_fatal_alert(
768                                w5500,
769                                AlertDescription::UnexpectedMessage,
770                                monotonic_secs,
771                            ));
772                        }
773                    };
774
775                match crypto::decrypt_record_inplace(
776                    w5500,
777                    self.sn,
778                    &key,
779                    &nonce,
780                    &header,
781                    &mut self.rx,
782                ) {
783                    Ok(Ok(content_type)) => content_type,
784                    Ok(Err(x)) => {
785                        error!("ContentType {:02X}", x);
786                        return Err(self.send_fatal_alert(
787                            w5500,
788                            AlertDescription::DecodeError,
789                            monotonic_secs,
790                        ));
791                    }
792                    Err(e) => return Err(self.send_fatal_alert(w5500, e, monotonic_secs)),
793                }
794            } else {
795                if let Err(e) = self.recv_unencrypted_body(w5500, &header) {
796                    return Err(self.send_fatal_alert(w5500, e, monotonic_secs));
797                }
798                header.content_type()
799            };
800
801        debug!("RecordHeader.content_type={:?}", actual_content_type);
802
803        if matches!(actual_content_type, ContentType::ApplicationData) {
804            self.rx.increment_application_data_tail(
805                header
806                    .length()
807                    .saturating_sub((GCM_TAG_LEN + 1) as u16)
808                    .into(),
809            );
810        }
811
812        if rx_buffer_contains_handshake_fragment
813            && !matches!(actual_content_type, ContentType::Handshake)
814        {
815            // https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
816            error!("Handshake messages MUST NOT be interleaved with other record types");
817            return Err(self.send_fatal_alert(
818                w5500,
819                AlertDescription::UnexpectedMessage,
820                monotonic_secs,
821            ));
822        }
823
824        let ret = match actual_content_type {
825            // https://datatracker.ietf.org/doc/html/rfc8446#section-5.1
826            // No mention if change_cipher_spec may or may not be fragmented
827            // This is such a short ContentType that I will assume that it
828            // does not fragment
829            ContentType::ChangeCipherSpec => {
830                if let Err(e) = self.recv_change_cipher_spec(&header) {
831                    Err(self.send_fatal_alert(w5500, e, monotonic_secs))
832                } else {
833                    Ok(None)
834                }
835            }
836            // "Alert messages MUST NOT be fragmented across records"
837            ContentType::Alert => return Err(self.recv_alert(w5500, &header)),
838            ContentType::Handshake => {
839                if let Err(e) = self.recv_handshake(monotonic_secs) {
840                    Err(self.send_fatal_alert(w5500, e, monotonic_secs))
841                } else {
842                    Ok(None)
843                }
844            }
845            ContentType::ApplicationData => Ok(Some(Event::ApplicationData)),
846        };
847
848        if matches!(header.content_type(), ContentType::ApplicationData) {
849            self.key_schedule.increment_read_record_sequence_number();
850        }
851
852        ret
853    }
854
855    fn recv_alert<W5500: Registers>(&mut self, w5500: &mut W5500, header: &RecordHeader) -> Error {
856        self.set_state(State::Reset);
857        self.key_schedule.reset();
858
859        if header.length() != 2 {
860            error!("expected length 2 for Alert got {}", header.length());
861            self.rx.reset();
862            w5500.tcp_disconnect(self.sn).ok();
863            Error::Client(Alert {
864                level: AlertLevel::Fatal,
865                description: AlertDescription::DecodeError,
866            })
867        } else {
868            let description: AlertDescription = match self.rx.pop_tail() {
869                Some(byte) => match AlertDescription::try_from(byte) {
870                    Ok(description) => description,
871                    Err(e) => {
872                        error!("unknown alert description {}", e);
873                        return Error::Client(Alert {
874                            level: AlertLevel::Fatal,
875                            description: AlertDescription::DecodeError,
876                        });
877                    }
878                },
879                None => {
880                    self.rx.reset();
881                    return Error::Client(Alert {
882                        level: AlertLevel::Fatal,
883                        description: AlertDescription::DecodeError,
884                    });
885                }
886            };
887
888            let level: AlertLevel = match self.rx.pop_tail() {
889                Some(byte) => match AlertLevel::try_from(byte) {
890                    Ok(level) => level,
891                    Err(e) => {
892                        error!("illegal alert level {}", e);
893                        AlertLevel::Fatal
894                    }
895                },
896                None => {
897                    self.rx.reset();
898                    return Error::Client(Alert {
899                        level: AlertLevel::Fatal,
900                        description: AlertDescription::DecodeError,
901                    });
902                }
903            };
904
905            let alert: Alert = Alert { level, description };
906
907            match level {
908                AlertLevel::Warning => warn!("{:?}", alert),
909                AlertLevel::Fatal => error!("{:?}", alert),
910            }
911
912            self.rx.reset();
913            Error::Server(alert)
914        }
915    }
916
917    fn send_client_finished<W5500: Registers>(
918        &mut self,
919        w5500: &mut W5500,
920    ) -> Result<(), AlertDescription> {
921        let verify_data: GenericArray<u8, U32> = self.key_schedule.client_finished_verify_data();
922        let data: [u8; 36] = handshake::client_finished(&verify_data);
923
924        self.send_encrypted_record(w5500, ContentType::Handshake, &data)
925            .map_err(AlertDescription::map_w5500)?;
926        self.set_state(State::Connected);
927
928        // master secrets are only ClientHello..server Finished
929        // no need to update the key schedule for this.
930        self.key_schedule.initialize_master_secret();
931
932        Ok(())
933    }
934
935    // helper to send an encrypted record without a round-trip to the socket
936    // buffers
937    fn send_encrypted_record<W5500: Registers>(
938        &mut self,
939        w5500: &mut W5500,
940        content_type: ContentType,
941        data: &[u8],
942    ) -> Result<(), HlError<W5500::Error>> {
943        const CONTENT_TYPE_LEN: usize = 1;
944        let data_len: u16 = unwrap!((data.len() + GCM_TAG_LEN + CONTENT_TYPE_LEN).try_into());
945
946        let header: [u8; 5] = [
947            ContentType::ApplicationData.into(),
948            TlsVersion::V1_2.msb(),
949            TlsVersion::V1_2.lsb(),
950            (data_len >> 8) as u8,
951            data_len as u8,
952        ];
953
954        let mut writer: TcpWriter<W5500> = w5500.tcp_writer(self.sn)?;
955
956        // write the record header
957        writer.write_all(&header)?;
958
959        let (key, nonce): ([u8; 16], [u8; 12]) = self.key_schedule.client_key_and_nonce().unwrap();
960        let mut cipher = crate::crypto::Aes128Gcm::new(&key, &nonce, &header);
961
962        // write the record data in 128-bit chunks
963        let mut chunks = data.chunks_exact(16);
964        for chunk in &mut chunks {
965            let mut mut_chunck: [u8; 16] = chunk.try_into().unwrap();
966            cipher.encrypt_block_inplace(&mut mut_chunck);
967            writer.write_all(&mut_chunck)?;
968        }
969
970        // write the remaining data
971        let rem = chunks.remainder();
972        let mut padded_block: [u8; 16] = [0; 16];
973        padded_block[..rem.len()].copy_from_slice(rem);
974        // append the content type
975        padded_block[rem.len()] = content_type as u8;
976        let remainder_len: usize = rem.len() + CONTENT_TYPE_LEN;
977        cipher.encrypt_remainder_inplace(&mut padded_block, remainder_len);
978        writer.write_all(&padded_block[..remainder_len])?;
979
980        // write the AES-GCM authentication tag
981        let tag: [u8; GCM_TAG_LEN] = cipher.finish();
982        writer.write_all(&tag)?;
983        writer.send()?;
984
985        Ok(())
986    }
987
988    fn recv_handshake(&mut self, monotonic_secs: u32) -> Result<(), AlertDescription> {
989        loop {
990            let mut hash: Sha256 = self.key_schedule.transcript_hash();
991            let (header, mut reader) = match self.rx.pop_handshake_record(&mut hash)? {
992                // fragment is not long enough to contain handshake type + length
993                None => return Ok(()),
994                Some(s) => s,
995            };
996
997            match header.msg_type() {
998                Ok(HandshakeType::ClientHello) => {
999                    error!("unexpected ClientHello");
1000                    return Err(AlertDescription::UnexpectedMessage);
1001                }
1002                Ok(HandshakeType::ServerHello) => {
1003                    if self.state != State::WaitServerHello {
1004                        error!("unexpected ServerHello in state {:?}", self.state);
1005                        return Err(AlertDescription::UnexpectedMessage);
1006                    } else {
1007                        let public_key: PublicKey = handshake::recv_server_hello(&mut reader)?;
1008
1009                        self.key_schedule.set_server_public_key(public_key);
1010                        self.key_schedule.set_transcript_hash(hash.clone());
1011                        self.key_schedule.initialize_handshake_secret();
1012                        self.set_state_with_timeout(State::WaitEncryptedExtensions, monotonic_secs);
1013                    }
1014                }
1015                Ok(HandshakeType::NewSessionTicket) => {
1016                    if self.state != State::Connected {
1017                        error!("unexpected NewSessionTicket in state {:?}", self.state);
1018                        return Err(AlertDescription::UnexpectedMessage);
1019                    } else {
1020                        // https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.1
1021                        // At any time after the server has received the client Finished
1022                        // message, it MAY send a NewSessionTicket message.
1023                        // The client MAY use this PSK for future handshakes by including the
1024                        // ticket value in the "pre_shared_key" extension in its ClientHello
1025                        info!("NewSessionTicket is unused");
1026                    }
1027                }
1028                Ok(HandshakeType::EndOfEarlyData) => {
1029                    // should never occur unless we support PSK
1030                    // https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.10
1031                    error!("PSK is not supported");
1032                    return Err(AlertDescription::UnexpectedMessage);
1033                }
1034                Ok(HandshakeType::EncryptedExtensions) => {
1035                    if self.state != State::WaitEncryptedExtensions {
1036                        error!("unexpected Certificate in state {:?}", self.state);
1037                        return Err(AlertDescription::UnexpectedMessage);
1038                    }
1039
1040                    handshake::recv_encrypted_extensions(&mut reader)?;
1041                    self.set_state_with_timeout(State::WaitFinished, monotonic_secs);
1042                }
1043                Ok(
1044                    hs_type @ (HandshakeType::Certificate
1045                    | HandshakeType::CertificateRequest
1046                    | HandshakeType::CertificateVerify),
1047                ) => {
1048                    error!(
1049                        "unexpected extension {:?} certificate authentication not supported",
1050                        hs_type
1051                    );
1052                    return Err(AlertDescription::UnexpectedMessage);
1053                }
1054                Ok(HandshakeType::Finished) => {
1055                    if self.state != State::WaitFinished {
1056                        error!("unexpected Finished in state {:?}", self.state);
1057                        return Err(AlertDescription::UnexpectedMessage);
1058                    }
1059
1060                    const VERIFY_DATA_LEN: usize = 32;
1061                    if header.length() != VERIFY_DATA_LEN as u32 {
1062                        error!(
1063                            "expected verify_data length {} got {}",
1064                            VERIFY_DATA_LEN,
1065                            header.length()
1066                        );
1067                        return Err(AlertDescription::UnexpectedMessage);
1068                    }
1069
1070                    let verify_data: [u8; 32] = reader.next_n()?;
1071                    self.key_schedule.verify_server_finished(&verify_data)?;
1072                    self.set_state_with_timeout(State::SendFinished, monotonic_secs);
1073                }
1074
1075                Ok(HandshakeType::KeyUpdate) => {
1076                    if self.state != State::Connected {
1077                        // https://datatracker.ietf.org/doc/html/rfc8446#section-4.6.3
1078                        // Implementations that receive a KeyUpdate message prior to
1079                        // receiving a Finished message MUST terminate the connection
1080                        // with an "unexpected_message"
1081                        error!("unexpected KeyUpdate in state {:?}", self.state);
1082                        return Err(AlertDescription::UnexpectedMessage);
1083                    }
1084
1085                    const EXPECTED_LEN: u32 = 1;
1086                    if header.length() != EXPECTED_LEN {
1087                        error!(
1088                            "expected KeyUpdate length {} got {}",
1089                            EXPECTED_LEN,
1090                            header.length()
1091                        );
1092                        return Err(AlertDescription::UnexpectedMessage);
1093                    }
1094
1095                    match handshake::KeyUpdateRequest::try_from(reader.next_u8()?) {
1096                        Ok(handshake::KeyUpdateRequest::UpdateNotRequested) => {
1097                            // should never occur because we never request a key update
1098                            warn!("KeyUpdate without update_requested");
1099                        }
1100                        Ok(handshake::KeyUpdateRequest::UpdateRequested) => {
1101                            warn!("TODO update_traffic_secret is untested");
1102                            self.key_schedule.update_traffic_secret();
1103                        }
1104                        Err(x) => {
1105                            error!("illegal KeyUpdateRequest value: 0x{:02X}", x);
1106                            return Err(AlertDescription::IllegalParameter);
1107                        }
1108                    }
1109                }
1110                Err(x) => {
1111                    warn!("invalid msg_type {:?}", x);
1112                    return Err(AlertDescription::UnexpectedMessage);
1113                }
1114            }
1115
1116            self.key_schedule.set_transcript_hash(hash);
1117        }
1118    }
1119
1120    /// Returns `true` if the TLS handshake has completed and the client is
1121    /// connected.
1122    ///
1123    /// # Example
1124    ///
1125    /// ```
1126    /// # const MY_KEY: [u8; 1] = [0];
1127    /// use w5500_tls::{
1128    ///     Client,
1129    ///     {
1130    ///         hl::Hostname,
1131    ///         ll::{
1132    ///             net::{Ipv4Addr, SocketAddrV4},
1133    ///             Sn,
1134    ///         },
1135    ///     },
1136    /// };
1137    ///
1138    /// static mut RX: [u8; 2048] = [0; 2048];
1139    ///
1140    /// const DST: SocketAddrV4 = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 4), 8883);
1141    /// const HOSTNAME: Hostname = Hostname::new_unwrapped("server.local");
1142    /// const SRC_PORT: u16 = 1234;
1143    /// const TLS_SN: Sn = Sn::Sn4;
1144    ///
1145    /// let tls_client: Client<2048> = Client::new(
1146    ///     TLS_SN,
1147    ///     SRC_PORT,
1148    ///     HOSTNAME,
1149    ///     DST,
1150    ///     b"mykeyidentity",
1151    ///     &MY_KEY,
1152    ///     unsafe { &mut RX },
1153    /// );
1154    //
1155    // assert_eq!(tls_client.connected(), false);
1156    // ```
1157    pub fn connected(&self) -> bool {
1158        self.state == State::Connected
1159    }
1160
1161    /// Create a TLS writer.
1162    ///
1163    /// This returns a [`TlsWriter`] structure, which contains functions to
1164    /// stream data to the W5500 socket buffers incrementally.
1165    ///
1166    /// This is similar to [`TcpWriter`], except it will encrypt the data before
1167    /// sending.
1168    ///
1169    /// This is slower than [`write_all`](Self::write_all), it will
1170    /// write all your data, read it back, encrypt it, then write it back
1171    /// before sending.  This is useful for low-memory applications.
1172    ///
1173    /// # Errors
1174    ///
1175    /// This method can only return:
1176    ///
1177    /// * [`Error::Client`] with [`AlertDescription::InternalError`]
1178    /// * [`Error::NotConnected`]
1179    ///
1180    /// # Example
1181    ///
1182    /// See [`TlsWriter`].
1183    pub fn writer<'w, 'ks, W5500: Registers>(
1184        &'ks mut self,
1185        w5500: &'w mut W5500,
1186    ) -> Result<TlsWriter<'w, 'ks, W5500>, Error>
1187    where
1188        Self: Sized,
1189    {
1190        const TRAILING_CONTENT_TYPE_LEN: u16 = 1;
1191        const RECORD_HEADER_LEN: u16 = RecordHeader::LEN as u16;
1192        const TLS_OVERHEAD: u16 =
1193            RECORD_HEADER_LEN + (GCM_TAG_LEN as u16) + TRAILING_CONTENT_TYPE_LEN;
1194
1195        if !self.connected() {
1196            return Err(Error::NotConnected);
1197        }
1198
1199        // if there is not enough space for the TLS overhead return an error
1200        let sn_tx_fsr: u16 = w5500
1201            .sn_tx_fsr(self.sn)
1202            .map_err(|_| Error::Client(Alert::new_warning(AlertDescription::InternalError)))?
1203            .checked_sub(TLS_OVERHEAD)
1204            .ok_or_else(|| Error::Client(Alert::new_warning(AlertDescription::InternalError)))?;
1205
1206        // advance write pointer by 5 to leave room for the record header
1207        let sn_tx_wr: u16 = w5500
1208            .sn_tx_wr(self.sn)
1209            .map_err(|_| Error::Client(Alert::new_warning(AlertDescription::InternalError)))?
1210            .wrapping_add(RECORD_HEADER_LEN);
1211
1212        Ok(TlsWriter {
1213            w5500,
1214            key_schedule: &mut self.key_schedule,
1215            sn: self.sn,
1216            head_ptr: sn_tx_wr,
1217            tail_ptr: sn_tx_wr.wrapping_add(sn_tx_fsr),
1218            ptr: sn_tx_wr,
1219        })
1220    }
1221
1222    /// Send data to the remote host.
1223    ///
1224    /// This is more efficient than [`writer`](Self::writer) because the data
1225    /// size is known up-front and a round-trip to the socket buffers to
1226    /// encrypt the record can be avoided.
1227    ///
1228    /// This should only be used when the handshake has completed, otherwise
1229    /// the server will send an `unexpected_message` alert.
1230    ///
1231    /// # Errors
1232    ///
1233    /// This method can only return:
1234    ///
1235    /// * [`Error::Client`] with [`AlertDescription::InternalError`]
1236    /// * [`Error::NotConnected`]
1237    pub fn write_all<W5500: Registers>(
1238        &mut self,
1239        w5500: &mut W5500,
1240        data: &[u8],
1241    ) -> Result<(), Error> {
1242        if !self.connected() {
1243            Err(Error::NotConnected)
1244        } else {
1245            self.send_encrypted_record(w5500, ContentType::ApplicationData, data)
1246                .map_err(|_| Error::Client(Alert::new_warning(AlertDescription::InternalError)))
1247        }
1248    }
1249
1250    /// Create a TLS reader.
1251    ///
1252    /// # Errors
1253    ///
1254    /// This method can only return:
1255    ///
1256    /// * [`HlError::Other`]
1257    /// * [`HlError::WouldBlock`]
1258    ///
1259    /// # Example
1260    ///
1261    /// See [`TlsReader`].
1262    pub fn reader<'ptr>(&'ptr mut self) -> Result<TlsReader<'b, 'ptr>, HlError<Infallible>> {
1263        self.rx.app_data_reader()
1264    }
1265}