/src/botan/src/lib/tls/tls_handshake_transitions.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * TLS Handshake State Transitions |
3 | | * (C) 2004-2006,2011,2012 Jack Lloyd |
4 | | * 2017 Harry Reimann, Rohde & Schwarz Cybersecurity |
5 | | * |
6 | | * Botan is released under the Simplified BSD License (see license.txt) |
7 | | */ |
8 | | |
9 | | #include <botan/internal/tls_handshake_transitions.h> |
10 | | |
11 | | #include <botan/tls_exceptn.h> |
12 | | |
13 | | #include <sstream> |
14 | | |
15 | | namespace Botan::TLS { |
16 | | |
17 | | namespace { |
18 | | |
19 | 241k | uint32_t bitmask_for_handshake_type(Handshake_Type type) { |
20 | 241k | switch(type) { |
21 | 286 | case Handshake_Type::HelloVerifyRequest: |
22 | 286 | return (1 << 0); |
23 | | |
24 | 321 | case Handshake_Type::HelloRequest: |
25 | 321 | return (1 << 1); |
26 | | |
27 | 61.4k | case Handshake_Type::ClientHello: |
28 | 61.4k | return (1 << 2); |
29 | | |
30 | 5.28k | case Handshake_Type::ServerHello: |
31 | 5.28k | return (1 << 3); |
32 | | |
33 | 15.7k | case Handshake_Type::Certificate: |
34 | 15.7k | return (1 << 4); |
35 | | |
36 | 268 | case Handshake_Type::CertificateUrl: |
37 | 268 | return (1 << 5); |
38 | | |
39 | 268 | case Handshake_Type::CertificateStatus: |
40 | 268 | return (1 << 6); |
41 | | |
42 | 272 | case Handshake_Type::ServerKeyExchange: |
43 | 272 | return (1 << 7); |
44 | | |
45 | 271 | case Handshake_Type::CertificateRequest: |
46 | 271 | return (1 << 8); |
47 | | |
48 | 273 | case Handshake_Type::ServerHelloDone: |
49 | 273 | return (1 << 9); |
50 | | |
51 | 268 | case Handshake_Type::CertificateVerify: |
52 | 268 | return (1 << 10); |
53 | | |
54 | 38.8k | case Handshake_Type::ClientKeyExchange: |
55 | 38.8k | return (1 << 11); |
56 | | |
57 | 269 | case Handshake_Type::NewSessionTicket: |
58 | 269 | return (1 << 12); |
59 | | |
60 | 115k | case Handshake_Type::HandshakeCCS: |
61 | 115k | return (1 << 13); |
62 | | |
63 | 1.00k | case Handshake_Type::Finished: |
64 | 1.00k | return (1 << 14); |
65 | | |
66 | 268 | case Handshake_Type::EndOfEarlyData: // RFC 8446 |
67 | 268 | return (1 << 15); |
68 | | |
69 | 269 | case Handshake_Type::EncryptedExtensions: // RFC 8446 |
70 | 269 | return (1 << 16); |
71 | | |
72 | 268 | case Handshake_Type::KeyUpdate: // RFC 8446 |
73 | 268 | return (1 << 17); |
74 | | |
75 | 8 | case Handshake_Type::HelloRetryRequest: // RFC 8446 |
76 | 8 | return (1 << 18); |
77 | | |
78 | | // allow explicitly disabling new handshakes |
79 | 234 | case Handshake_Type::None: |
80 | 234 | return 0; |
81 | 241k | } |
82 | | |
83 | 65 | throw TLS_Exception(Alert::UnexpectedMessage, |
84 | 65 | "Unknown TLS handshake message type " + std::to_string(static_cast<size_t>(type))); |
85 | 241k | } |
86 | | |
87 | 263 | std::string handshake_mask_to_string(uint32_t mask, char combiner) { |
88 | 263 | const Handshake_Type types[] = {Handshake_Type::HelloVerifyRequest, |
89 | 263 | Handshake_Type::HelloRequest, |
90 | 263 | Handshake_Type::ClientHello, |
91 | 263 | Handshake_Type::ServerHello, |
92 | 263 | Handshake_Type::Certificate, |
93 | 263 | Handshake_Type::CertificateUrl, |
94 | 263 | Handshake_Type::CertificateStatus, |
95 | 263 | Handshake_Type::ServerKeyExchange, |
96 | 263 | Handshake_Type::CertificateRequest, |
97 | 263 | Handshake_Type::ServerHelloDone, |
98 | 263 | Handshake_Type::CertificateVerify, |
99 | 263 | Handshake_Type::ClientKeyExchange, |
100 | 263 | Handshake_Type::NewSessionTicket, |
101 | 263 | Handshake_Type::HandshakeCCS, |
102 | 263 | Handshake_Type::Finished, |
103 | 263 | Handshake_Type::EndOfEarlyData, |
104 | 263 | Handshake_Type::EncryptedExtensions, |
105 | 263 | Handshake_Type::KeyUpdate}; |
106 | | |
107 | 263 | std::ostringstream o; |
108 | 263 | bool empty = true; |
109 | | |
110 | 4.73k | for(auto&& t : types) { |
111 | 4.73k | if(mask & bitmask_for_handshake_type(t)) { |
112 | 311 | if(!empty) { |
113 | 48 | o << combiner; |
114 | 48 | } |
115 | 311 | o << handshake_type_to_string(t); |
116 | 311 | empty = false; |
117 | 311 | } |
118 | 4.73k | } |
119 | | |
120 | 263 | return o.str(); |
121 | 263 | } |
122 | | |
123 | | } // namespace |
124 | | |
125 | 15.4k | bool Handshake_Transitions::received_handshake_msg(Handshake_Type msg_type) const { |
126 | 15.4k | const uint32_t mask = bitmask_for_handshake_type(msg_type); |
127 | | |
128 | 15.4k | return (m_hand_received_mask & mask) != 0; |
129 | 15.4k | } |
130 | | |
131 | 48.0k | void Handshake_Transitions::confirm_transition_to(Handshake_Type msg_type) { |
132 | 48.0k | const uint32_t mask = bitmask_for_handshake_type(msg_type); |
133 | | |
134 | 48.0k | m_hand_received_mask |= mask; |
135 | | |
136 | 48.0k | const bool ok = (m_hand_expecting_mask & mask) != 0; // overlap? |
137 | | |
138 | 48.0k | if(!ok) { |
139 | 204 | const uint32_t seen_so_far = m_hand_received_mask & ~mask; |
140 | | |
141 | 204 | std::ostringstream msg; |
142 | | |
143 | 204 | msg << "Unexpected state transition in handshake got a " << handshake_type_to_string(msg_type); |
144 | | |
145 | 204 | if(m_hand_expecting_mask == 0) { |
146 | 14 | msg << " not expecting messages"; |
147 | 190 | } else { |
148 | 190 | msg << " expected " << handshake_mask_to_string(m_hand_expecting_mask, '|'); |
149 | 190 | } |
150 | | |
151 | 204 | if(seen_so_far != 0) { |
152 | 73 | msg << " seen " << handshake_mask_to_string(seen_so_far, '+'); |
153 | 73 | } |
154 | | |
155 | 204 | throw Unexpected_Message(msg.str()); |
156 | 204 | } |
157 | | |
158 | | /* We don't know what to expect next, so force a call to |
159 | | set_expected_next; if it doesn't happen, the next transition |
160 | | check will always fail which is what we want. |
161 | | */ |
162 | 47.8k | m_hand_expecting_mask = 0; |
163 | 47.8k | } |
164 | | |
165 | 73.9k | void Handshake_Transitions::set_expected_next(Handshake_Type msg_type) { |
166 | 73.9k | m_hand_expecting_mask |= bitmask_for_handshake_type(msg_type); |
167 | 73.9k | } |
168 | | |
169 | 0 | void Handshake_Transitions::set_expected_next(const std::vector<Handshake_Type>& msg_types) { |
170 | 0 | for(const auto type : msg_types) { |
171 | 0 | set_expected_next(type); |
172 | 0 | } |
173 | 0 | } |
174 | | |
175 | 99.3k | bool Handshake_Transitions::change_cipher_spec_expected() const { |
176 | 99.3k | return (bitmask_for_handshake_type(Handshake_Type::HandshakeCCS) & m_hand_expecting_mask) != 0; |
177 | 99.3k | } |
178 | | |
179 | | } // namespace Botan::TLS |