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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

99.44
/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 {
23

24
using Test = Botan_Tests::Test;
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
      Botan_Tests::CHECK("empty read",
154
                         [&](auto& result) {
1✔
155
                            Handshake_Layer hl(Connection_Side::Client);
1✔
156
                            Transcript_Hash_State th("SHA-256");
1✔
157
                            result.confirm("needs header bytes", !hl.next_message(Policy(), th));
3✔
158
                            check_transcript_hash_empty(result, th);
1✔
159
                         }),
1✔
160

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

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

180
      Botan_Tests::CHECK("read server hello",
181
                         [&](auto& result) {
1✔
182
                            Handshake_Layer hl(Connection_Side::Client);
1✔
183
                            Transcript_Hash_State th("SHA-256");
1✔
184
                            hl.copy_data(server_hello_message);
1✔
185
                            result.confirm("is a server hello",
3✔
186
                                           has_message<Server_Hello_13>(result, hl.next_message(Policy(), th)));
2✔
187
                            check_transcript_hash_filled(result, th);
1✔
188
                         }),
2✔
189

190
      Botan_Tests::CHECK("read legacy server hello",
191
                         [&](auto& result) {
1✔
192
                            Handshake_Layer hl(Connection_Side::Client);
1✔
193
                            Transcript_Hash_State th("SHA-256");
1✔
194
                            hl.copy_data(server_hello_12_message);
1✔
195
                            result.confirm("is a legacy server hello",
3✔
196
                                           has_message<Server_Hello_12>(result, hl.next_message(Policy(), th)));
2✔
197
                            check_transcript_hash_filled(result, th);
1✔
198
                         }),
2✔
199

200
      Botan_Tests::CHECK("read client hello in two steps",
201
                         [&](auto& result) {
1✔
202
                            Handshake_Layer hl(Connection_Side::Client);
1✔
203
                            Transcript_Hash_State th("SHA-256");
1✔
204

205
                            const Botan::secure_vector<uint8_t> partial_client_hello_message(
1✔
206
                               client_hello_message.cbegin(), client_hello_message.cend() - 15);
1✔
207
                            hl.copy_data(partial_client_hello_message);
1✔
208
                            result.confirm("needs more bytes", !hl.next_message(Policy(), th));
3✔
209
                            result.confirm("holds pending message data", hl.has_pending_data());
3✔
210

211
                            const Botan::secure_vector<uint8_t> remaining_client_hello_message(
2✔
212
                               client_hello_message.cend() - 15, client_hello_message.cend());
1✔
213
                            hl.copy_data(remaining_client_hello_message);
1✔
214
                            result.confirm("is a client hello",
3✔
215
                                           has_message<Client_Hello_13>(result, hl.next_message(Policy(), th)));
2✔
216

217
                            check_transcript_hash_filled(result, th);
1✔
218
                         }),
3✔
219

220
      Botan_Tests::CHECK("read multiple messages",
221
                         [&](auto& result) {
1✔
222
                            Handshake_Layer hl(Connection_Side::Client);
1✔
223
                            Transcript_Hash_State th("SHA-256");
1✔
224
                            hl.copy_data(Botan::concat(server_hello_message, encrypted_extensions));
1✔
225
                            result.confirm("is a server hello",
3✔
226
                                           has_message<Server_Hello_13>(result, hl.next_message(Policy(), th)));
2✔
227
                            result.confirm("is encrypted extensions",
3✔
228
                                           has_message<Encrypted_Extensions>(result, hl.next_message(Policy(), th)));
2✔
229
                            check_transcript_hash_filled(result, th);
1✔
230
                         }),
2✔
231

232
      Botan_Tests::CHECK("reject TLS 1.2 messages",
233
                         [&](auto& result) {
1✔
234
                            for(const auto& msg : tls_12_only_messages) {
15✔
235
                               Handshake_Layer hl(Connection_Side::Client);
7✔
236
                               Transcript_Hash_State th("SHA-256");
7✔
237

238
                               hl.copy_data(msg);
7✔
239
                               result.template test_throws<TLS_Exception>("message is rejected",
21✔
240
                                                                          "Unknown handshake message received",
241
                                                                          [&] { hl.next_message(Policy(), th); });
7✔
242

243
                               check_transcript_hash_empty(result, th);
7✔
244
                            }
245
                         }),
1✔
246

247
      Botan_Tests::CHECK(
248
         "reject incomplete messages with invalid type",
249
         [&](auto& result) {
1✔
250
            // This is a regression test for BoGo "TLS13-WrongOuterRecord". We receive encrypted handshake messages
251
            // with the record type set to Handshake rather than Application Data. This exposed our handshake layer
252
            // to "random data" with an insensible type tag and a long (insensible) length field.
253
            // This caused a deadlock as we waited to receive the complete message, rather than validating the type
254
            // tag to exit early.
255
            const auto data = Botan::hex_decode_locked("D4B028717D0FA310FF8664127B9448D7952E06A4F9EA23");
1✔
256
            // data from the bogo test --          ~~~~~~ <- length
257
            //                                   ~~ <- bogus message type
258
            Handshake_Layer hl(Connection_Side::Client);
1✔
259
            Transcript_Hash_State th("SHA-256");
1✔
260
            hl.copy_data(data);
1✔
261
            result.template test_throws<TLS_Exception>(
3✔
262
               "message is rejected", "Unknown handshake message received", [&] { hl.next_message(Policy(), th); });
1✔
263
         }),
3✔
264
   };
10✔
265
}
266

267
std::vector<Test::Result> prepare_message() {
1✔
268
   return {
1✔
269
      Botan_Tests::CHECK("prepare client hello",
270
                         [&](auto& result) {
1✔
271
                            auto hello = std::get<Client_Hello_13>(Client_Hello_13::parse(
3✔
272
                               {client_hello_message.cbegin() + 4, client_hello_message.cend()}));
2✔
273
                            Handshake_Layer hl(Connection_Side::Client);
1✔
274
                            Transcript_Hash_State th("SHA-256");
1✔
275
                            result.test_eq(
2✔
276
                               "produces the same message", hl.prepare_message(hello, th), client_hello_message);
277
                            check_transcript_hash_filled(result, th);
1✔
278
                         }),
1✔
279

280
      Botan_Tests::CHECK("prepare server hello",
281
                         [&](auto& result) {
1✔
282
                            auto hello = std::get<Server_Hello_13>(Server_Hello_13::parse(
3✔
283
                               {server_hello_message.cbegin() + 4, server_hello_message.cend()}));
2✔
284
                            Handshake_Layer hl(Connection_Side::Server);
1✔
285
                            Transcript_Hash_State th("SHA-256");
1✔
286
                            result.test_eq(
2✔
287
                               "produces the same message", hl.prepare_message(hello, th), server_hello_message);
288
                            check_transcript_hash_filled(result, th);
1✔
289
                         }),
1✔
290
   };
3✔
291
}
292

293
std::vector<Test::Result> full_client_handshake() {
1✔
294
   Handshake_Layer hl(Connection_Side::Client);
1✔
295
   Transcript_Hash_State th;
1✔
296

297
   Text_Policy policy("minimum_rsa_bits = 1024");
1✔
298

299
   return {
1✔
300
      Botan_Tests::CHECK("client hello",
301
                         [&](auto& result) {
1✔
302
                            auto hello = std::get<Client_Hello_13>(Client_Hello_13::parse(
3✔
303
                               {client_hello_message.cbegin() + 4, client_hello_message.cend()}));
1✔
304
                            hl.prepare_message(hello, th);
1✔
305
                            check_transcript_hash_empty(result, th);
1✔
306
                         }),
1✔
307

308
      Botan_Tests::CHECK(
309
         "server hello",
310
         [&](auto& result) {
1✔
311
            hl.copy_data(server_hello_message);
1✔
312

313
            const auto server_hello = hl.next_message(policy, th);
1✔
314
            result.confirm("is a Server Hello", has_message<Server_Hello_13>(result, server_hello));
3✔
315

316
            // we now know the algorithm from the Server Hello
317
            th.set_algorithm("SHA-256");
1✔
318

319
            check_transcript_hash_filled(result, th);
1✔
320

321
            const auto expected_after_server_hello = Botan::hex_decode(
1✔
322
               "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");
323

324
            result.test_eq(
2✔
325
               "correct transcript hash produced after server hello", th.current(), expected_after_server_hello);
1✔
326
         }),
2✔
327

328
      Botan_Tests::CHECK(
329
         "server handshake messages",
330
         [&](auto& result) {
1✔
331
            hl.copy_data(server_handshake_messages);
1✔
332

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

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

339
            const auto expected_after_certificate = Botan::hex_decode(
1✔
340
               "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");
341

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

346
            const auto expected_after_server_finished = Botan::hex_decode(
1✔
347
               "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");
348

349
            const auto server_finished = hl.next_message(policy, th);
1✔
350
            result.confirm("is Finished", has_message<Finished_13>(result, server_finished));
2✔
351
            result.test_eq("hash is updated after server Finished", th.current(), expected_after_server_finished);
2✔
352
         }),
6✔
353

354
      Botan_Tests::CHECK(
355
         "client finished",
356
         [&](auto& result) {
1✔
357
            const auto expected_after_client_finished = Botan::hex_decode(
1✔
358
               "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");
359

360
            Finished_13 client_finished({client_finished_message.cbegin() + 4, client_finished_message.cend()});
2✔
361
            hl.prepare_message(client_finished, th);
1✔
362
            result.test_eq("hash is updated after client Finished", th.current(), expected_after_client_finished);
2✔
363
         }),
2✔
364
   };
5✔
365
}
2✔
366

367
std::vector<Test::Result> hello_retry_request_handshake() {
1✔
368
   Handshake_Layer hl(Connection_Side::Client);
1✔
369
   Transcript_Hash_State th;
1✔
370

371
   Text_Policy policy("minimum_rsa_bits = 1024");
1✔
372

373
   return {
1✔
374
      Botan_Tests::CHECK("client hello 1",
375
                         [&](auto& result) {
1✔
376
                            auto hello = std::get<Client_Hello_13>(Client_Hello_13::parse(
3✔
377
                               {hrr_client_hello_msg.cbegin() + 4, hrr_client_hello_msg.cend()}));
1✔
378
                            auto msg = hl.prepare_message(hello, th);
1✔
379
                            result.test_eq(
1✔
380
                               "parsing and re-marshalling produces same message", msg, hrr_client_hello_msg);
381
                            check_transcript_hash_empty(result, th);
1✔
382
                         }),
1✔
383

384
      Botan_Tests::CHECK("hello retry request",
385
                         [&](auto& result) {
1✔
386
                            hl.copy_data(hrr_hello_retry_request_msg);
1✔
387

388
                            const auto hrr = hl.next_message(policy, th);
1✔
389
                            result.confirm("is a Hello Retry Request", has_message<Hello_Retry_Request>(result, hrr));
3✔
390

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

395
                            check_transcript_hash_filled(result, th);
1✔
396

397
                            const auto expected_after_hello_retry_request =
×
398
                               Botan::hex_decode("74EEC04D09C926E86C0647C37BA4DC18D277EEC3337E4608C4D829B77E2FD2B3");
1✔
399

400
                            result.test_eq("correct transcript hash produced after hello retry request",
2✔
401
                                           th.current(),
1✔
402
                                           expected_after_hello_retry_request);
403
                         }),
2✔
404

405
      // ... the rest of the handshake will work just like in full_client_handshake
406
   };
3✔
407
}
2✔
408

409
}  // namespace
410

411
namespace Botan_Tests {
412
BOTAN_REGISTER_TEST_FN("tls",
413
                       "tls_handshake_layer_13",
414
                       read_handshake_messages,
415
                       prepare_message,
416
                       full_client_handshake,
417
                       hello_retry_request_handshake);
418
}
419

420
#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

© 2026 Coveralls, Inc