Coverage Report

Created: 2024-07-10 06:19

/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