1use crate::tls_alert::TlsAlertSeverity;
2use crate::tls_handshake::*;
3use crate::tls_message::*;
4
5#[derive(Debug, PartialEq, Eq)]
6pub enum StateChangeError {
8 InvalidTransition,
9 ParseError,
10}
11
12#[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 (TlsState::ClientHello, &TlsMessageHandshake::ServerHello(_), false) => Ok(TlsState::ServerHello),
60 (TlsState::ServerHello, &TlsMessageHandshake::Certificate(_), false) => Ok(TlsState::Certificate),
61 (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 (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 (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 (TlsState::Certificate, &TlsMessageHandshake::ServerDone(_), false) => Ok(TlsState::PskHelloDone),
80 (TlsState::PskHelloDone, &TlsMessageHandshake::ClientKeyExchange(_), true) => Ok(TlsState::PskCKE),
81 (TlsState::AskResumeSession, &TlsMessageHandshake::ServerHello(_), false) => Ok(TlsState::ResumeSession),
83 (TlsState::ResumeSession, &TlsMessageHandshake::Certificate(_), false) => Ok(TlsState::Certificate),
85 (TlsState::ClientHello, &TlsMessageHandshake::ServerHelloV13Draft18(_), false) => Ok(TlsState::ClientChangeCipherSpec),
88 (TlsState::None, &TlsMessageHandshake::HelloRequest, _) => Err(StateChangeError::InvalidTransition),
90 (s, &TlsMessageHandshake::HelloRequest, _) => Ok(s),
91 (TlsState::ClientChangeCipherSpec, &TlsMessageHandshake::NewSessionTicket(_), false) => Ok(TlsState::ClientChangeCipherSpec),
93 _ => Err(StateChangeError::InvalidTransition),
95 }
96}
97
98#[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 (TlsState::ClientKeyExchange, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
119 (TlsState::ClientChangeCipherSpec,&TlsMessage::ChangeCipherSpec, false) => Ok(TlsState::SessionEncrypted),
120 (TlsState::CRClientKeyExchange, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
122 (TlsState::CRCertVerify, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
123 (TlsState::NoCertCKE, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
125 (TlsState::PskCKE, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
127 (TlsState::ResumeSession, &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
129 (TlsState::AskResumeSession, &TlsMessage::ChangeCipherSpec, true) => Ok(TlsState::AskResumeSession),
131 (s, TlsMessage::Alert(a), _) => {
133 if a.severity == TlsAlertSeverity::Warning { Ok(s) } else { Ok(TlsState::Finished) }
134 },
135 (_,_,_) => Err(StateChangeError::InvalidTransition),
136 }
137}