• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 11844561993

14 Nov 2024 07:58PM UTC coverage: 91.178% (+0.1%) from 91.072%
11844561993

Pull #4435

github

web-flow
Merge 81dcb29da into e430f157a
Pull Request #4435: Test duration values ​​are now presented in seconds with six digits of precision. Tests without time measurements have been edited.

91856 of 100744 relevant lines covered (91.18%)

9311006.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.52
/src/tests/test_tls_handshake_layer_13.cpp
1
/*
2
* (C) 2022 Jack Lloyd
3
* (C) 2022 Hannes Rantzsch, René Meusel - neXenio
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_TLS_13)
11

12
   #include <botan/tls_exceptn.h>
13
   #include <botan/tls_magic.h>
14

15
   #include <botan/internal/stl_util.h>
16
   #include <botan/internal/tls_handshake_layer_13.h>
17
   #include <botan/internal/tls_handshake_state_13.h>
18
   #include <botan/internal/tls_transcript_hash_13.h>
19

20
using namespace Botan::TLS;
21

22
namespace Botan_Tests {
23

24
namespace {
25

26
template <typename T>
27
bool has_message(Test::Result& test_result, const std::optional<Handshake_Message_13>& read_result) {
12✔
28
   test_result.require("has a message", read_result.has_value());
24✔
29
   return std::holds_alternative<T>(read_result.value());
12✔
30
}
31

32
template <typename T>
33
const Handshake_Message_13& get_message(Test::Result& test_result,
34
                                        const std::optional<Handshake_Message_13>& read_result) {
35
   test_result.require("has the expected message", has_message<T>(test_result, read_result));
36
   return std::get<T>(read_result.value());
37
}
38

39
const auto client_hello_message = Botan::hex_decode_locked(  // from RFC 8448
40
   "01 00 00 c0 03 03 cb"
41
   "34 ec b1 e7 81 63 ba 1c 38 c6 da cb 19 6a 6d ff a2 1a 8d 99 12"
42
   "ec 18 a2 ef 62 83 02 4d ec e7 00 00 06 13 01 13 03 13 02 01 00"
43
   "00 91 00 00 00 0b 00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01"
44
   "00 00 0a 00 14 00 12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02"
45
   "01 03 01 04 00 23 00 00 00 33 00 26 00 24 00 1d 00 20 99 38 1d"
46
   "e5 60 e4 bd 43 d2 3d 8e 43 5a 7d ba fe b3 c0 6e 51 c1 3c ae 4d"
47
   "54 13 69 1e 52 9a af 2c 00 2b 00 03 02 03 04 00 0d 00 20 00 1e"
48
   "04 03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02"
49
   "01 04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01");
50

51
const auto server_hello_message = Botan::hex_decode_locked(
52
   "02 00 00 56 03 03 a6"
53
   "af 06 a4 12 18 60 dc 5e 6e 60 24 9c d3 4c 95 93 0c 8a c5 cb 14"
54
   "34 da c1 55 77 2e d3 e2 69 28 00 13 01 00 00 2e 00 33 00 24 00"
55
   "1d 00 20 c9 82 88 76 11 20 95 fe 66 76 2b db f7 c6 72 e1 56 d6"
56
   "cc 25 3b 83 3d f1 dd 69 b1 b0 4e 75 1f 0f 00 2b 00 02 03 04");
57

58
const auto server_hello_12_message = Botan::hex_decode_locked(
59
   "02 00 00 3e 03 03 ff ea 0b cf ba 56 4a 4c e1 77 c6 a4 44 b0 eb"
60
   "df f5 62 9b 27 72 93 c6 18 c1 12 5f 23 1e 86 28 dd 00 c0 30 00"
61
   "00 16 ff 01 00 01 00 00 0b 00 04 03 00 01 02 00 23 00 00 00 0f"
62
   "00 01 01");
63

64
const auto encrypted_extensions = Botan::hex_decode_locked(
65
   "08 00 00 24 00 22 00 0a 00 14 00"
66
   "12 00 1d 00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c"
67
   "00 02 40 01 00 00 00 00");
68

69
const auto server_handshake_messages =  // except server hello
70
   Botan::hex_decode_locked(
71
      "08 00 00 24 00 22 00 0a 00 14 00 12 00 1d"
72
      "00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c 00 02 40"
73
      "01 00 00 00 00 0b 00 01 b9 00 00 01 b5 00 01 b0 30 82 01 ac 30"
74
      "82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 86 48 86 f7 0d"
75
      "01 01 0b 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03 72 73 61"
76
      "30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 35 39 5a 17 0d 32 36"
77
      "30 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 06 03 55 04"
78
      "03 13 03 72 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01"
79
      "01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 bb 49 8f 82 79 30"
80
      "3d 98 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26 d3 90 1a"
81
      "24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c 1a f1 9e"
82
      "aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc b0 52 4b 1b 01"
83
      "8c 3e 0b 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74 80 30 53"
84
      "0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93 ef f0 ab"
85
      "9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 03 01 00 01"
86
      "a3 1a 30 18 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06 03 55 1d"
87
      "0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05"
88
      "00 03 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a 72 67 17"
89
      "06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea e8 f8 a5"
90
      "8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 03 01 51 56 72"
91
      "60 96 fd 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be c1 fc 63"
92
      "a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b 1c 3b 84"
93
      "e0 a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 f8 96 12 29"
94
      "ac 91 87 b4 2b 4d e1 00 00 0f 00 00 84 08 04 00 80 5a 74 7c 5d"
95
      "88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a b3"
96
      "ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 3a 5c 14 1a 07 86"
97
      "53 fa 6b ef 78 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b be"
98
      "8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44 5c"
99
      "9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 d3 be 15 2a 3d"
100
      "a5 04 3e 06 3d da 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3 14 00"
101
      "00 20 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4 de da 4a b4 2c"
102
      "30 95 72 cb 7f ff ee 54 54 b7 8f 07 18");
103

104
const auto client_finished_message = Botan::hex_decode_locked(
105
   "14 00 00 20 a8 ec 43 6d 67 76 34 ae 52 5a c1"
106
   "fc eb e1 1a 03 9e c1 76 94 fa c6 e9 85 27 b6 42 f2 ed d5 ce 61");
107

108
//
109
// ###################################################################
110
//
111

112
const auto hrr_client_hello_msg = Botan::hex_decode_locked(
113
   "01 00 00 b0 03 03 b0 b1 c5 a5 aa 37 c5"
114
   "91 9f 2e d1 d5 c6 ff f7 fc b7 84 97 16 94 5a 2b 8c ee 92 58 a3"
115
   "46 67 7b 6f 00 00 06 13 01 13 03 13 02 01 00 00 81 00 00 00 0b"
116
   "00 09 00 00 06 73 65 72 76 65 72 ff 01 00 01 00 00 0a 00 08 00"
117
   "06 00 1d 00 17 00 18 00 33 00 26 00 24 00 1d 00 20 e8 e8 e3 f3"
118
   "b9 3a 25 ed 97 a1 4a 7d ca cb 8a 27 2c 62 88 e5 85 c6 48 4d 05"
119
   "26 2f ca d0 62 ad 1f 00 2b 00 03 02 03 04 00 0d 00 20 00 1e 04"
120
   "03 05 03 06 03 02 03 08 04 08 05 08 06 04 01 05 01 06 01 02 01"
121
   "04 02 05 02 06 02 02 02 00 2d 00 02 01 01 00 1c 00 02 40 01");
122

123
const auto hrr_hello_retry_request_msg = Botan::hex_decode_locked(
124
   "02 00 00 ac 03 03 cf 21 ad 74 e5 9a 61"
125
   "11 be 1d 8c 02 1e 65 b8 91 c2 a2 11 16 7a bb 8c 5e 07 9e 09 e2"
126
   "c8 a8 33 9c 00 13 01 00 00 84 00 33 00 02 00 17 00 2c 00 74 00"
127
   "72 71 dc d0 4b b8 8b c3 18 91 19 39 8a 00 00 00 00 ee fa fc 76"
128
   "c1 46 b8 23 b0 96 f8 aa ca d3 65 dd 00 30 95 3f 4e df 62 56 36"
129
   "e5 f2 1b b2 e2 3f cc 65 4b 1b 5b 40 31 8d 10 d1 37 ab cb b8 75"
130
   "74 e3 6e 8a 1f 02 5f 7d fa 5d 6e 50 78 1b 5e da 4a a1 5b 0c 8b"
131
   "e7 78 25 7d 16 aa 30 30 e9 e7 84 1d d9 e4 c0 34 22 67 e8 ca 0c"
132
   "af 57 1f b2 b7 cf f0 f9 34 b0 00 2b 00 02 03 04");
133

134
const std::vector<Botan::secure_vector<uint8_t>> tls_12_only_messages{
135
   {static_cast<uint8_t>(Handshake_Type::HelloRequest), 0x00, 0x00, 0x02, 0x42, 0x42},
136
   {static_cast<uint8_t>(Handshake_Type::HelloVerifyRequest), 0x00, 0x00, 0x02, 0x42, 0x42},
137
   {static_cast<uint8_t>(Handshake_Type::ServerKeyExchange), 0x00, 0x00, 0x02, 0x42, 0x42},
138
   {static_cast<uint8_t>(Handshake_Type::ServerHelloDone), 0x00, 0x00, 0x02, 0x42, 0x42},
139
   {static_cast<uint8_t>(Handshake_Type::ClientKeyExchange), 0x00, 0x00, 0x02, 0x42, 0x42},
140
   {static_cast<uint8_t>(Handshake_Type::CertificateUrl), 0x00, 0x00, 0x02, 0x42, 0x42},
141
   {static_cast<uint8_t>(Handshake_Type::CertificateStatus), 0x00, 0x00, 0x02, 0x42, 0x42}};
142

143
void check_transcript_hash_empty(Test::Result& result, const Transcript_Hash_State& transcript_hash) {
11✔
144
   result.test_throws<Botan::Invalid_State>("empty transcript_hash throws", [&] { transcript_hash.current(); });
33✔
145
}
11✔
146

147
void check_transcript_hash_filled(Test::Result& result, const Transcript_Hash_State& transcript_hash) {
9✔
148
   result.test_no_throw("non-empty transcript_hash", [&] { transcript_hash.current(); });
27✔
149
}
9✔
150

151
std::vector<Test::Result> read_handshake_messages() {
1✔
152
   return {
1✔
153
      CHECK("empty read",
154
            [&](auto& result) {
1✔
155
               result.start_timer();
1✔
156
               Handshake_Layer hl(Connection_Side::Client);
1✔
157
               Transcript_Hash_State th("SHA-256");
1✔
158
               result.confirm("needs header bytes", !hl.next_message(Policy(), th));
2✔
159
               check_transcript_hash_empty(result, th);
1✔
160
               result.end_timer();
1✔
161
            }),
1✔
162

163
      CHECK("read incomplete header",
164
            [&](auto& result) {
1✔
165
               result.start_timer();
1✔
166
               Handshake_Layer hl(Connection_Side::Client);
1✔
167
               Transcript_Hash_State th("SHA-256");
1✔
168
               hl.copy_data(std::vector<uint8_t>{0x00, 0x01, 0x02});
1✔
169
               result.confirm("needs more bytes", !hl.next_message(Policy(), th));
2✔
170
               check_transcript_hash_empty(result, th);
1✔
171
               result.end_timer();
1✔
172
            }),
2✔
173

174
      CHECK("read client hello",
175
            [&](auto& result) {
1✔
176
               result.start_timer();
1✔
177
               Handshake_Layer hl(Connection_Side::Client);
1✔
178
               Transcript_Hash_State th("SHA-256");
1✔
179
               hl.copy_data(client_hello_message);
1✔
180
               result.confirm("is a client hello", has_message<Client_Hello_13>(result, hl.next_message(Policy(), th)));
3✔
181
               check_transcript_hash_filled(result, th);
1✔
182
               result.end_timer();
1✔
183
            }),
2✔
184

185
      CHECK("read server hello",
186
            [&](auto& result) {
1✔
187
               result.start_timer();
1✔
188
               Handshake_Layer hl(Connection_Side::Client);
1✔
189
               Transcript_Hash_State th("SHA-256");
1✔
190
               hl.copy_data(server_hello_message);
1✔
191
               result.confirm("is a server hello", has_message<Server_Hello_13>(result, hl.next_message(Policy(), th)));
3✔
192
               check_transcript_hash_filled(result, th);
1✔
193
               result.end_timer();
1✔
194
            }),
2✔
195

196
      CHECK("read legacy server hello",
197
            [&](auto& result) {
1✔
198
               result.start_timer();
1✔
199
               Handshake_Layer hl(Connection_Side::Client);
1✔
200
               Transcript_Hash_State th("SHA-256");
1✔
201
               hl.copy_data(server_hello_12_message);
1✔
202
               result.confirm("is a legacy server hello",
2✔
203
                              has_message<Server_Hello_12>(result, hl.next_message(Policy(), th)));
2✔
204
               check_transcript_hash_filled(result, th);
1✔
205
               result.end_timer();
1✔
206
            }),
2✔
207

208
      CHECK("read client hello in two steps",
209
            [&](auto& result) {
1✔
210
               result.start_timer();
1✔
211
               Handshake_Layer hl(Connection_Side::Client);
1✔
212
               Transcript_Hash_State th("SHA-256");
1✔
213

214
               const Botan::secure_vector<uint8_t> partial_client_hello_message(client_hello_message.cbegin(),
1✔
215
                                                                                client_hello_message.cend() - 15);
1✔
216
               hl.copy_data(partial_client_hello_message);
1✔
217
               result.confirm("needs more bytes", !hl.next_message(Policy(), th));
2✔
218
               result.confirm("holds pending message data", hl.has_pending_data());
2✔
219

220
               const Botan::secure_vector<uint8_t> remaining_client_hello_message(client_hello_message.cend() - 15,
1✔
221
                                                                                  client_hello_message.cend());
222
               hl.copy_data(remaining_client_hello_message);
1✔
223
               result.confirm("is a client hello", has_message<Client_Hello_13>(result, hl.next_message(Policy(), th)));
3✔
224

225
               check_transcript_hash_filled(result, th);
1✔
226
               result.end_timer();
1✔
227
            }),
3✔
228

229
      CHECK("read multiple messages",
230
            [&](auto& result) {
1✔
231
               result.start_timer();
1✔
232
               Handshake_Layer hl(Connection_Side::Client);
1✔
233
               Transcript_Hash_State th("SHA-256");
1✔
234
               hl.copy_data(Botan::concat(server_hello_message, encrypted_extensions));
1✔
235
               result.confirm("is a server hello", has_message<Server_Hello_13>(result, hl.next_message(Policy(), th)));
3✔
236
               result.confirm("is encrypted extensions",
2✔
237
                              has_message<Encrypted_Extensions>(result, hl.next_message(Policy(), th)));
2✔
238
               check_transcript_hash_filled(result, th);
1✔
239
               result.end_timer();
1✔
240
            }),
2✔
241

242
      CHECK("reject TLS 1.2 messages",
243
            [&](auto& result) {
1✔
244
               result.start_timer();
1✔
245
               for(const auto& msg : tls_12_only_messages) {
15✔
246
                  Handshake_Layer hl(Connection_Side::Client);
7✔
247
                  Transcript_Hash_State th("SHA-256");
7✔
248

249
                  hl.copy_data(msg);
7✔
250
                  result.template test_throws<TLS_Exception>("message is rejected",
14✔
251
                                                             "Unknown handshake message received",
252
                                                             [&] { hl.next_message(Policy(), th); });
14✔
253

254
                  check_transcript_hash_empty(result, th);
7✔
255
               }
256
               result.end_timer();
1✔
257
            }),
1✔
258

259
      CHECK("reject incomplete messages with invalid type",
260
            [&](auto& result) {
1✔
261
               // This is a regression test for BoGo "TLS13-WrongOuterRecord". We receive encrypted handshake messages
262
               // with the record type set to Handshake rather than Application Data. This exposed our handshake layer
263
               // to "random data" with an insensible type tag and a long (insensible) length field.
264
               // This caused a deadlock as we waited to receive the complete message, rather than validating the type
265
               // tag to exit early.
266
               result.start_timer();
1✔
267
               const auto data = Botan::hex_decode_locked("D4B028717D0FA310FF8664127B9448D7952E06A4F9EA23");
1✔
268
               // data from the bogo test --          ~~~~~~ <- length
269
               //                                   ~~ <- bogus message type
270
               Handshake_Layer hl(Connection_Side::Client);
1✔
271
               Transcript_Hash_State th("SHA-256");
1✔
272
               hl.copy_data(data);
1✔
273
               result.template test_throws<TLS_Exception>(
2✔
274
                  "message is rejected", "Unknown handshake message received", [&] { hl.next_message(Policy(), th); });
2✔
275
               result.end_timer();
1✔
276
            }),
3✔
277
   };
10✔
278
}
1✔
279

280
std::vector<Test::Result> prepare_message() {
1✔
281
   return {
1✔
282
      CHECK("prepare client hello",
283
            [&](auto& result) {
1✔
284
               result.start_timer();
1✔
285
               auto hello = std::get<Client_Hello_13>(
4✔
286
                  Client_Hello_13::parse({client_hello_message.cbegin() + 4, client_hello_message.cend()}));
1✔
287
               Handshake_Layer hl(Connection_Side::Client);
1✔
288
               Transcript_Hash_State th("SHA-256");
1✔
289
               result.test_eq("produces the same message", hl.prepare_message(hello, th), client_hello_message);
2✔
290
               check_transcript_hash_filled(result, th);
1✔
291
               result.end_timer();
1✔
292
            }),
1✔
293

294
      CHECK("prepare server hello",
295
            [&](auto& result) {
1✔
296
               result.start_timer();
1✔
297
               auto hello = std::get<Server_Hello_13>(
4✔
298
                  Server_Hello_13::parse({server_hello_message.cbegin() + 4, server_hello_message.cend()}));
1✔
299
               Handshake_Layer hl(Connection_Side::Server);
1✔
300
               Transcript_Hash_State th("SHA-256");
1✔
301
               result.test_eq("produces the same message", hl.prepare_message(hello, th), server_hello_message);
2✔
302
               check_transcript_hash_filled(result, th);
1✔
303
               result.end_timer();
1✔
304
            }),
1✔
305
   };
3✔
306
}
1✔
307

308
std::vector<Test::Result> full_client_handshake() {
1✔
309
   Handshake_Layer hl(Connection_Side::Client);
1✔
310
   Transcript_Hash_State th;
1✔
311

312
   Text_Policy policy("minimum_rsa_bits = 1024");
1✔
313

314
   return {
1✔
315
      CHECK("client hello",
316
            [&](auto& result) {
1✔
317
               result.start_timer();
1✔
318
               auto hello = std::get<Client_Hello_13>(
3✔
319
                  Client_Hello_13::parse({client_hello_message.cbegin() + 4, client_hello_message.cend()}));
1✔
320
               hl.prepare_message(hello, th);
1✔
321
               check_transcript_hash_empty(result, th);
1✔
322
               result.end_timer();
1✔
323
            }),
1✔
324

325
      CHECK("server hello",
326
            [&](auto& result) {
1✔
327
               result.start_timer();
1✔
328
               hl.copy_data(server_hello_message);
1✔
329

330
               const auto server_hello = hl.next_message(policy, th);
1✔
331
               result.confirm("is a Server Hello", has_message<Server_Hello_13>(result, server_hello));
2✔
332

333
               // we now know the algorithm from the Server Hello
334
               th.set_algorithm("SHA-256");
1✔
335

336
               check_transcript_hash_filled(result, th);
1✔
337

338
               const auto expected_after_server_hello = Botan::hex_decode(
1✔
339
                  "86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8");
340

341
               result.test_eq(
1✔
342
                  "correct transcript hash produced after server hello", th.current(), expected_after_server_hello);
1✔
343
               result.end_timer();
1✔
344
            }),
2✔
345

346
      CHECK("server handshake messages",
347
            [&](auto& result) {
1✔
348
               result.start_timer();
1✔
349
               hl.copy_data(server_handshake_messages);
1✔
350

351
               const auto enc_exts = hl.next_message(policy, th);
1✔
352
               result.confirm("is Encrypted Extensions", has_message<Encrypted_Extensions>(result, enc_exts));
2✔
353

354
               const auto cert = hl.next_message(policy, th);
1✔
355
               result.confirm("is Certificate", has_message<Certificate_13>(result, cert));
2✔
356

357
               const auto expected_after_certificate = Botan::hex_decode(
1✔
358
                  "76 4d 66 32 b3 c3 5c 3f 32 05 e3 49 9a c3 ed ba ab b8 82 95 fb a7 51 46 1d 36 78 e2 e5 ea 06 87");
359

360
               const auto cert_verify = hl.next_message(policy, th);
1✔
361
               result.confirm("is Certificate Verify", has_message<Certificate_Verify_13>(result, cert_verify));
2✔
362
               result.test_eq("hash before Cert Verify is still available", th.previous(), expected_after_certificate);
2✔
363

364
               const auto expected_after_server_finished = Botan::hex_decode(
1✔
365
                  "96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a 00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13");
366

367
               const auto server_finished = hl.next_message(policy, th);
1✔
368
               result.confirm("is Finished", has_message<Finished_13>(result, server_finished));
2✔
369
               result.test_eq("hash is updated after server Finished", th.current(), expected_after_server_finished);
1✔
370
               result.end_timer();
1✔
371
            }),
6✔
372

373
      CHECK("client finished",
374
            [&](auto& result) {
1✔
375
               result.start_timer();
1✔
376
               const auto expected_after_client_finished = Botan::hex_decode(
1✔
377
                  "20 91 45 a9 6e e8 e2 a1 22 ff 81 00 47 cc 95 26 84 65 8d 60 49 e8 64 29 42 6d b8 7c 54 ad 14 3d");
378

379
               Finished_13 client_finished({client_finished_message.cbegin() + 4, client_finished_message.cend()});
2✔
380
               hl.prepare_message(client_finished, th);
1✔
381
               result.test_eq("hash is updated after client Finished", th.current(), expected_after_client_finished);
1✔
382
               result.end_timer();
1✔
383
            }),
2✔
384
   };
5✔
385
}
3✔
386

387
std::vector<Test::Result> hello_retry_request_handshake() {
1✔
388
   Handshake_Layer hl(Connection_Side::Client);
1✔
389
   Transcript_Hash_State th;
1✔
390

391
   Text_Policy policy("minimum_rsa_bits = 1024");
1✔
392

393
   return {
1✔
394
      CHECK("client hello 1",
395
            [&](auto& result) {
1✔
396
               result.start_timer();
1✔
397
               auto hello = std::get<Client_Hello_13>(
3✔
398
                  Client_Hello_13::parse({hrr_client_hello_msg.cbegin() + 4, hrr_client_hello_msg.cend()}));
1✔
399
               auto msg = hl.prepare_message(hello, th);
1✔
400
               result.test_eq("parsing and re-marshalling produces same message", msg, hrr_client_hello_msg);
1✔
401
               check_transcript_hash_empty(result, th);
1✔
402
               result.end_timer();
1✔
403
            }),
1✔
404

405
      CHECK("hello retry request",
406
            [&](auto& result) {
1✔
407
               result.start_timer();
1✔
408
               hl.copy_data(hrr_hello_retry_request_msg);
1✔
409

410
               const auto hrr = hl.next_message(policy, th);
1✔
411
               result.confirm("is a Hello Retry Request", has_message<Hello_Retry_Request>(result, hrr));
2✔
412

413
               // we now know the algorithm from the Hello Retry Request
414
               // which will not change with the future Server Hello anymore (RFC 8446 4.1.4)
415
               th = Transcript_Hash_State::recreate_after_hello_retry_request("SHA-256", th);
1✔
416

417
               check_transcript_hash_filled(result, th);
1✔
418

419
               const auto expected_after_hello_retry_request =
×
420
                  Botan::hex_decode("74EEC04D09C926E86C0647C37BA4DC18D277EEC3337E4608C4D829B77E2FD2B3");
1✔
421

422
               result.test_eq("correct transcript hash produced after hello retry request",
1✔
423
                              th.current(),
1✔
424
                              expected_after_hello_retry_request);
425
               result.end_timer();
1✔
426
            }),
2✔
427

428
      // ... the rest of the handshake will work just like in full_client_handshake
429
   };
3✔
430
}
3✔
431

432
BOTAN_REGISTER_TEST_FN("tls",
433
                       "tls_handshake_layer_13",
434
                       read_handshake_messages,
435
                       prepare_message,
436
                       full_client_handshake,
437
                       hello_retry_request_handshake);
438

439
}  // namespace
440

441
}  // namespace Botan_Tests
442

443
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc