tls_parser/
tls_states.rs

1use crate::tls_alert::TlsAlertSeverity;
2use crate::tls_handshake::*;
3use crate::tls_message::*;
4
5#[derive(Debug, PartialEq, Eq)]
6/// Error types for the state machine
7pub enum StateChangeError {
8    InvalidTransition,
9    ParseError,
10}
11
12/// TLS machine possible states
13#[derive(Copy, Clone, Debug, PartialEq)]
14pub enum TlsState {
15    None,
16    ClientHello,
17    AskResumeSession,
18    ResumeSession,
19    ServerHello,
20    Certificate,
21    CertificateSt,
22    ServerKeyExchange,
23    ServerHelloDone,
24    ClientKeyExchange,
25    ClientChangeCipherSpec,
26
27    CRCertRequest,
28    CRHelloDone,
29    CRCert,
30    CRClientKeyExchange,
31    CRCertVerify,
32
33    NoCertSKE,
34    NoCertHelloDone,
35    NoCertCKE,
36
37    PskHelloDone,
38    PskCKE,
39
40    SessionEncrypted,
41
42    Alert,
43
44    Finished,
45
46    Invalid,
47}
48
49#[rustfmt::skip]
50fn tls_state_transition_handshake(state: TlsState, msg: &TlsMessageHandshake, to_server:bool) -> Result<TlsState,StateChangeError> {
51    match (state,msg,to_server) {
52        (TlsState::None,             TlsMessageHandshake::ClientHello(msg), true) => {
53            match msg.session_id {
54                Some(_) => Ok(TlsState::AskResumeSession),
55                _       => Ok(TlsState::ClientHello)
56            }
57        },
58        // Server certificate
59        (TlsState::ClientHello,      &TlsMessageHandshake::ServerHello(_), false)       => Ok(TlsState::ServerHello),
60        (TlsState::ServerHello,      &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::Certificate),
61        // Server certificate, no client certificate requested
62        (TlsState::Certificate,      &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
63        (TlsState::Certificate,      &TlsMessageHandshake::CertificateStatus(_), false) => Ok(TlsState::CertificateSt),
64        (TlsState::CertificateSt,    &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
65        (TlsState::ServerKeyExchange,&TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::ServerHelloDone),
66        (TlsState::ServerHelloDone  ,&TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::ClientKeyExchange),
67        // Server certificate, client certificate requested
68        (TlsState::Certificate,      &TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
69        (TlsState::ServerKeyExchange,&TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
70        (TlsState::CRCertRequest,    &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::CRHelloDone),
71        (TlsState::CRHelloDone,      &TlsMessageHandshake::Certificate(_), true)        => Ok(TlsState::CRCert),
72        (TlsState::CRCert,           &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::CRClientKeyExchange),
73        (TlsState::CRClientKeyExchange, &TlsMessageHandshake::CertificateVerify(_), _)  => Ok(TlsState::CRCertVerify),
74        // Server has no certificate (but accepts anonymous)
75        (TlsState::ServerHello,      &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::NoCertSKE),
76        (TlsState::NoCertSKE,        &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::NoCertHelloDone),
77        (TlsState::NoCertHelloDone,  &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::NoCertCKE),
78        // PSK
79        (TlsState::Certificate,      &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::PskHelloDone),
80        (TlsState::PskHelloDone,     &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::PskCKE),
81        // Resuming session
82        (TlsState::AskResumeSession, &TlsMessageHandshake::ServerHello(_), false)       => Ok(TlsState::ResumeSession),
83        // Resume session failed
84        (TlsState::ResumeSession,    &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::Certificate),
85        // TLS 1.3 Draft 18 1-RTT
86        // Re-use the ClientChangeCipherSpec state to indicate the next message will be encrypted
87        (TlsState::ClientHello,      &TlsMessageHandshake::ServerHelloV13Draft18(_), false)    => Ok(TlsState::ClientChangeCipherSpec),
88        // Hello requests must be accepted at any time (except start), but ignored [RFC5246] 7.4.1.1
89        (TlsState::None,             &TlsMessageHandshake::HelloRequest, _)             => Err(StateChangeError::InvalidTransition),
90        (s,                          &TlsMessageHandshake::HelloRequest, _)             => Ok(s),
91        // NewSessionTicket message (after CCS)
92        (TlsState::ClientChangeCipherSpec,    &TlsMessageHandshake::NewSessionTicket(_), false)  => Ok(TlsState::ClientChangeCipherSpec),
93        // All other transitions are considered invalid
94        _ => Err(StateChangeError::InvalidTransition),
95    }
96}
97
98/// Update the TLS state machine, doing one transition
99///
100/// Given the previous state and the parsed message, return the new state or a state machine error.
101///
102/// This state machine only implements the TLS handshake.
103///
104/// Some transitions only check the new message type, while some others must match the content
105/// (for example, to check if the client asked to resume a session).
106///
107/// If the previous state is `Invalid`, the state machine will not return an error, but keep the
108/// same `Invalid` state. This is used to raise error only once if the state machine keeps being
109/// updated by new messages.
110#[rustfmt::skip]
111pub fn tls_state_transition(state: TlsState, msg: &TlsMessage, to_server:bool) -> Result<TlsState,StateChangeError> {
112    match (state,msg,to_server) {
113        (TlsState::Invalid,_,_) => Ok(TlsState::Invalid),
114        (TlsState::SessionEncrypted,_, _) => Ok(TlsState::SessionEncrypted),
115        (TlsState::Finished,_,_) => Ok(TlsState::Invalid),
116        (_,TlsMessage::Handshake(m),_) => tls_state_transition_handshake(state,m,to_server),
117        // Server certificate
118        (TlsState::ClientKeyExchange,     &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
119        (TlsState::ClientChangeCipherSpec,&TlsMessage::ChangeCipherSpec, false) => Ok(TlsState::SessionEncrypted),
120        // Server certificate, client certificate requested
121        (TlsState::CRClientKeyExchange,   &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
122        (TlsState::CRCertVerify,          &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
123        // No server certificate
124        (TlsState::NoCertCKE,             &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
125        // PSK
126        (TlsState::PskCKE,                &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
127        // Resume session
128        (TlsState::ResumeSession,         &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
129        // 0-rtt
130        (TlsState::AskResumeSession,      &TlsMessage::ChangeCipherSpec, true) => Ok(TlsState::AskResumeSession),
131        // non-fatal alerts
132        (s,                     TlsMessage::Alert(a), _) => {
133            if a.severity == TlsAlertSeverity::Warning { Ok(s) } else { Ok(TlsState::Finished) }
134        },
135        (_,_,_) => Err(StateChangeError::InvalidTransition),
136    }
137}