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

randombit / botan / 16072710435

04 Jul 2025 11:26AM UTC coverage: 90.571% (-0.005%) from 90.576%
16072710435

push

github

web-flow
Merge pull request #4958 from randombit/jack/fix-clang-tidy-modernize-avoid-bind

Enable and fix clang-tidy warning modernize-avoid-bind

99057 of 109369 relevant lines covered (90.57%)

12345728.62 hits per line

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

99.5
/src/tests/test_tls_cipher_state.cpp
1
/*
2
* (C) 2021 Jack Lloyd
3
* (C) 2021 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/secmem.h>
13
   #include <botan/tls_ciphersuite.h>
14

15
   #include <botan/internal/tls_channel_impl_13.h>
16
   #include <botan/internal/tls_cipher_state.h>
17

18
namespace Botan_Tests {
19

20
namespace {
21

22
using namespace Botan;
23
using namespace Botan::TLS;
24

25
class Journaling_Secret_Logger : public Secret_Logger {
2✔
26
   public:
27
      void maybe_log_secret(std::string_view label, std::span<const uint8_t> secret) const override {
26✔
28
         secrets[std::string(label)] = std::vector<uint8_t>(secret.begin(), secret.end());
52✔
29
      }
26✔
30

31
   public:
32
      mutable std::map<std::string, std::vector<uint8_t>> secrets;  // NOLINT(*-non-private-member-variable*)
33
};
34

35
decltype(auto) make_CHECK_both(Cipher_State* cs_client,
2✔
36
                               Journaling_Secret_Logger* sl_client,
37
                               Cipher_State* cs_server,
38
                               Journaling_Secret_Logger* sl_server) {
39
   using namespace std::placeholders;
2✔
40
   return [=](const std::string& name, auto lambda) -> std::vector<Test::Result> {
16✔
41
      // NOLINTBEGIN(*-avoid-bind)
42
      return {CHECK(std::string(name + " (client)").c_str(),
×
43
                    std::bind(lambda, cs_client, sl_client, Connection_Side::Client, _1)),
14✔
44
              CHECK(std::string(name + " (server)").c_str(),
×
45
                    std::bind(lambda, cs_server, sl_server, Connection_Side::Server, _1))};
56✔
46
      // NOLINTEND(*-avoid-bind)
47
   };
30✔
48
}
49

50
class RFC8448_TestData {
51
   private:
52
      const std::string name;
53
      const Connection_Side emitter;
54
      const std::vector<uint8_t> record_header;
55
      const secure_vector<uint8_t> encrypted_fragment;
56
      const secure_vector<uint8_t> plaintext_fragment;
57

58
   public:
59
      RFC8448_TestData(std::string n,
9✔
60
                       Connection_Side em,
61
                       std::vector<uint8_t> rh,
62
                       secure_vector<uint8_t> ef,
63
                       secure_vector<uint8_t> pf) :
9✔
64
            name(std::move(n)),
9✔
65
            emitter(em),
9✔
66
            record_header(std::move(rh)),
9✔
67
            encrypted_fragment(std::move(ef)),
9✔
68
            plaintext_fragment(std::move(pf)) {}
9✔
69

70
      void encrypt(Test::Result& result, Cipher_State* cs) const {
9✔
71
         auto plaintext_fragment_copy = plaintext_fragment;
9✔
72
         result.test_no_throw("encryption is successful for " + name,
18✔
73
                              [&] { cs->encrypt_record_fragment(record_header, plaintext_fragment_copy); });
18✔
74

75
         result.test_eq("encrypted payload for " + name, plaintext_fragment_copy, encrypted_fragment);
18✔
76
      }
9✔
77

78
      void decrypt(Test::Result& result, Cipher_State* cs) const {
9✔
79
         auto encrypted_fragment_copy = encrypted_fragment;
9✔
80
         result.test_no_throw("decryption is successful for " + name,
18✔
81
                              [&] { cs->decrypt_record_fragment(record_header, encrypted_fragment_copy); });
18✔
82

83
         result.test_eq("plaintext for " + name, encrypted_fragment_copy, plaintext_fragment);
18✔
84
      }
9✔
85

86
      void xxcrypt(Test::Result& result, Cipher_State* cs, Connection_Side side) const {
18✔
87
         if(emitter == side) {
18✔
88
            encrypt(result, cs);
9✔
89
         } else {
90
            decrypt(result, cs);
9✔
91
         }
92
      }
18✔
93
};
94

95
std::vector<Test::Result> test_secret_derivation_rfc8448_rtt1() {
1✔
96
   // shared secret
97
   const auto shared_secret = Botan::hex_decode_locked(
1✔
98
      "8b d4 05 4f b5 5b 9d 63 fd fb ac f9 f0 4b 9f 0d"
99
      "35 e6 d6 3f 53 75 63 ef d4 62 72 90 0f 89 49 2d");
1✔
100

101
   const auto expected_psk = Botan::hex_decode_locked(
1✔
102
      "4e cd 0e b6 ec 3b 4d 87 f5 d6 02 8f 92 2c a4 c5"
103
      "85 1a 27 7f d4 13 11 c9 e6 2d 2c 94 92 e1 c4 f3");
1✔
104

105
   // this is not part of RFC 8448
106
   const std::string export_label = "export_test_label";
1✔
107
   const std::string export_context = "rfc8448_rtt1";
1✔
108
   const auto expected_key_export = Botan::hex_decode_locked("f2 00 58 a6 5c e0 43 0a 19 79 44 c8 12 43 1c 2d");
1✔
109

110
   // transcript hash from client hello and server hello
111
   const auto th_server_hello = Botan::hex_decode(
1✔
112
      "86 0c 06 ed c0 78 58 ee 8e 78 f0 e7 42 8c 58 ed"
113
      "d6 b4 3f 2c a3 e6 e9 5f 02 ed 06 3c f0 e1 ca d8");
1✔
114

115
   // transcript hash from client hello up to (excluding) server finished
116
   const auto th_pre_server_finished = Botan::hex_decode(
1✔
117
      "ed b7 72 5f a7 a3 47 3b 03 1e c8 ef 65 a2 48 54"
118
      "93 90 01 38 a2 b9 12 91 40 7d 79 51 a0 61 10 ed");
1✔
119

120
   // transcript hash from client hello up to (including) server finished
121
   const auto th_server_finished = Botan::hex_decode(
1✔
122
      "96 08 10 2a 0f 1c cc 6d b6 25 0b 7b 7e 41 7b 1a"
123
      "00 0e aa da 3d aa e4 77 7a 76 86 c9 ff 83 df 13");
1✔
124

125
   // transcript hash from client hello up to (including) client finished
126
   const auto th_client_finished = Botan::hex_decode(
1✔
127
      "20 91 45 a9 6e e8 e2 a1 22 ff 81 00 47 cc 95 26"
128
      "84 65 8d 60 49 e8 64 29 42 6d b8 7c 54 ad 14 3d");
1✔
129

130
   // handshake traffic secret for the client
131
   const auto client_handshake_traffic_secret = Botan::hex_decode(
1✔
132
      "b3 ed db 12 6e 06 7f 35 a7 80 b3 ab f4 5e 2d 8f"
133
      "3b 1a 95 07 38 f5 2e 96 00 74 6a 0e 27 a5 5a 21");
1✔
134

135
   // handshake traffic secret for the server
136
   const auto server_handshake_traffic_secret = Botan::hex_decode(
1✔
137
      "b6 7b 7d 69 0c c1 6c 4e 75 e5 42 13 cb 2d 37 b4"
138
      "e9 c9 12 bc de d9 10 5d 42 be fd 59 d3 91 ad 38");
1✔
139

140
   // application traffic secret (0) for the client
141
   const auto client_traffic_secret = Botan::hex_decode(
1✔
142
      "9e 40 64 6c e7 9a 7f 9d c0 5a f8 88 9b ce 65 52"
143
      "87 5a fa 0b 06 df 00 87 f7 92 eb b7 c1 75 04 a5");
1✔
144

145
   // application traffic secret (0) for the server
146
   const auto server_traffic_secret = Botan::hex_decode(
1✔
147
      "a1 1a f9 f0 55 31 f8 56 ad 47 11 6b 45 a9 50 32"
148
      "82 04 b4 f4 4b fb 6b 3a 4b 4f 1f 3f cb 63 16 43");
1✔
149

150
   // application traffic secret (1) for the client (not in RFC 8448)
151
   const auto updated_client_traffic_secret = Botan::hex_decode(
1✔
152
      "fc df cc 72 72 5a ae e4 8b f6 4e 4f d8 b7 49 cd"
153
      "bd ba b3 9d 90 da 0b 26 e2 24 5c a6 ea 16 72 07");
1✔
154

155
   // application traffic secret (1) for the server (not in RFC 8448)
156
   const auto updated_server_traffic_secret = Botan::hex_decode(
1✔
157
      "51 92 1b 8a a3 00 19 76 eb 40 1d 0a 43 19 a8 51"
158
      "64 16 a6 c5 60 01 a3 57 e5 d1 62 03 1e 84 f9 16");
1✔
159

160
   // encrypted with server_handshake_traffic_secret
161
   const auto encrypted_extensions =
1✔
162
      RFC8448_TestData("encrypted_extensions",
163
                       Connection_Side::Server,
164
                       Botan::hex_decode("17 03 03 02 a2"),
2✔
165
                       Botan::hex_decode_locked("d1 ff 33 4a 56 f5 bf"
2✔
166
                                                "f6 59 4a 07 cc 87 b5 80 23 3f 50 0f 45 e4 89 e7 f3 3a f3 5e df"
167
                                                "78 69 fc f4 0a a4 0a a2 b8 ea 73 f8 48 a7 ca 07 61 2e f9 f9 45"
168
                                                "cb 96 0b 40 68 90 51 23 ea 78 b1 11 b4 29 ba 91 91 cd 05 d2 a3"
169
                                                "89 28 0f 52 61 34 aa dc 7f c7 8c 4b 72 9d f8 28 b5 ec f7 b1 3b"
170
                                                "d9 ae fb 0e 57 f2 71 58 5b 8e a9 bb 35 5c 7c 79 02 07 16 cf b9"
171
                                                "b1 18 3e f3 ab 20 e3 7d 57 a6 b9 d7 47 76 09 ae e6 e1 22 a4 cf"
172
                                                "51 42 73 25 25 0c 7d 0e 50 92 89 44 4c 9b 3a 64 8f 1d 71 03 5d"
173
                                                "2e d6 5b 0e 3c dd 0c ba e8 bf 2d 0b 22 78 12 cb b3 60 98 72 55"
174
                                                "cc 74 41 10 c4 53 ba a4 fc d6 10 92 8d 80 98 10 e4 b7 ed 1a 8f"
175
                                                "d9 91 f0 6a a6 24 82 04 79 7e 36 a6 a7 3b 70 a2 55 9c 09 ea d6"
176
                                                "86 94 5b a2 46 ab 66 e5 ed d8 04 4b 4c 6d e3 fc f2 a8 94 41 ac"
177
                                                "66 27 2f d8 fb 33 0e f8 19 05 79 b3 68 45 96 c9 60 bd 59 6e ea"
178
                                                "52 0a 56 a8 d6 50 f5 63 aa d2 74 09 96 0d ca 63 d3 e6 88 61 1e"
179
                                                "a5 e2 2f 44 15 cf 95 38 d5 1a 20 0c 27 03 42 72 96 8a 26 4e d6"
180
                                                "54 0c 84 83 8d 89 f7 2c 24 46 1a ad 6d 26 f5 9e ca ba 9a cb bb"
181
                                                "31 7b 66 d9 02 f4 f2 92 a3 6a c1 b6 39 c6 37 ce 34 31 17 b6 59"
182
                                                "62 22 45 31 7b 49 ee da 0c 62 58 f1 00 d7 d9 61 ff b1 38 64 7e"
183
                                                "92 ea 33 0f ae ea 6d fa 31 c7 a8 4d c3 bd 7e 1b 7a 6c 71 78 af"
184
                                                "36 87 90 18 e3 f2 52 10 7f 24 3d 24 3d c7 33 9d 56 84 c8 b0 37"
185
                                                "8b f3 02 44 da 8c 87 c8 43 f5 e5 6e b4 c5 e8 28 0a 2b 48 05 2c"
186
                                                "f9 3b 16 49 9a 66 db 7c ca 71 e4 59 94 26 f7 d4 61 e6 6f 99 88"
187
                                                "2b d8 9f c5 08 00 be cc a6 2d 6c 74 11 6d bd 29 72 fd a1 fa 80"
188
                                                "f8 5d f8 81 ed be 5a 37 66 89 36 b3 35 58 3b 59 91 86 dc 5c 69"
189
                                                "18 a3 96 fa 48 a1 81 d6 b6 fa 4f 9d 62 d5 13 af bb 99 2f 2b 99"
190
                                                "2f 67 f8 af e6 7f 76 91 3f a3 88 cb 56 30 c8 ca 01 e0 c6 5d 11"
191
                                                "c6 6a 1e 2a c4 c8 59 77 b7 c7 a6 99 9b bf 10 dc 35 ae 69 f5 51"
192
                                                "56 14 63 6c 0b 9b 68 c1 9e d2 e3 1c 0b 3b 66 76 30 38 eb ba 42"
193
                                                "f3 b3 8e dc 03 99 f3 a9 f2 3f aa 63 97 8c 31 7f c9 fa 66 a7 3f"
194
                                                "60 f0 50 4d e9 3b 5b 84 5e 27 55 92 c1 23 35 ee 34 0b bc 4f dd"
195
                                                "d5 02 78 40 16 e4 b3 be 7e f0 4d da 49 f4 b4 40 a3 0c b5 d2 af"
196
                                                "93 98 28 fd 4a e3 79 4e 44 f9 4d f5 a6 31 ed e4 2c 17 19 bf da"
197
                                                "bf 02 53 fe 51 75 be 89 8e 75 0e dc 53 37 0d 2b"),
198
                       Botan::hex_decode_locked("08 00 00 24 00 22 00 0a 00 14 00 12 00 1d"
1✔
199
                                                "00 17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c 00 02 40"
200
                                                "01 00 00 00 00 0b 00 01 b9 00 00 01 b5 00 01 b0 30 82 01 ac 30"
201
                                                "82 01 15 a0 03 02 01 02 02 01 02 30 0d 06 09 2a 86 48 86 f7 0d"
202
                                                "01 01 0b 05 00 30 0e 31 0c 30 0a 06 03 55 04 03 13 03 72 73 61"
203
                                                "30 1e 17 0d 31 36 30 37 33 30 30 31 32 33 35 39 5a 17 0d 32 36"
204
                                                "30 37 33 30 30 31 32 33 35 39 5a 30 0e 31 0c 30 0a 06 03 55 04"
205
                                                "03 13 03 72 73 61 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d 01 01"
206
                                                "01 05 00 03 81 8d 00 30 81 89 02 81 81 00 b4 bb 49 8f 82 79 30"
207
                                                "3d 98 08 36 39 9b 36 c6 98 8c 0c 68 de 55 e1 bd b8 26 d3 90 1a"
208
                                                "24 61 ea fd 2d e4 9a 91 d0 15 ab bc 9a 95 13 7a ce 6c 1a f1 9e"
209
                                                "aa 6a f9 8c 7c ed 43 12 09 98 e1 87 a8 0e e0 cc b0 52 4b 1b 01"
210
                                                "8c 3e 0b 63 26 4d 44 9a 6d 38 e2 2a 5f da 43 08 46 74 80 30 53"
211
                                                "0e f0 46 1c 8c a9 d9 ef bf ae 8e a6 d1 d0 3e 2b d1 93 ef f0 ab"
212
                                                "9a 80 02 c4 74 28 a6 d3 5a 8d 88 d7 9f 7f 1e 3f 02 03 01 00 01"
213
                                                "a3 1a 30 18 30 09 06 03 55 1d 13 04 02 30 00 30 0b 06 03 55 1d"
214
                                                "0f 04 04 03 02 05 a0 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b 05"
215
                                                "00 03 81 81 00 85 aa d2 a0 e5 b9 27 6b 90 8c 65 f7 3a 72 67 17"
216
                                                "06 18 a5 4c 5f 8a 7b 33 7d 2d f7 a5 94 36 54 17 f2 ea e8 f8 a5"
217
                                                "8c 8f 81 72 f9 31 9c f3 6b 7f d6 c5 5b 80 f2 1a 03 01 51 56 72"
218
                                                "60 96 fd 33 5e 5e 67 f2 db f1 02 70 2e 60 8c ca e6 be c1 fc 63"
219
                                                "a4 2a 99 be 5c 3e b7 10 7c 3c 54 e9 b9 eb 2b d5 20 3b 1c 3b 84"
220
                                                "e0 a8 b2 f7 59 40 9b a3 ea c9 d9 1d 40 2d cc 0c c8 f8 96 12 29"
221
                                                "ac 91 87 b4 2b 4d e1 00 00 0f 00 00 84 08 04 00 80 5a 74 7c 5d"
222
                                                "88 fa 9b d2 e5 5a b0 85 a6 10 15 b7 21 1f 82 4c d4 84 14 5a b3"
223
                                                "ff 52 f1 fd a8 47 7b 0b 7a bc 90 db 78 e2 d3 3a 5c 14 1a 07 86"
224
                                                "53 fa 6b ef 78 0c 5e a2 48 ee aa a7 85 c4 f3 94 ca b6 d3 0b be"
225
                                                "8d 48 59 ee 51 1f 60 29 57 b1 54 11 ac 02 76 71 45 9e 46 44 5c"
226
                                                "9e a5 8c 18 1e 81 8e 95 b8 c3 fb 0b f3 27 84 09 d3 be 15 2a 3d"
227
                                                "a5 04 3e 06 3d da 65 cd f5 ae a2 0d 53 df ac d4 2f 74 f3 14 00"
228
                                                "00 20 9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4 de da 4a b4 2c"
229
                                                "30 95 72 cb 7f ff ee 54 54 b7 8f 07 18"
230
                                                "16" /* to-be-encrypted content type */));
1✔
231

232
   // encrypted with client_handshake_traffic_secret
233
   const auto encrypted_client_finished_message =
1✔
234
      RFC8448_TestData("encrypted_client_finished_message",
235
                       Connection_Side::Client,
236
                       Botan::hex_decode("17 03 03 00 35"),
2✔
237
                       Botan::hex_decode_locked("75 ec 4d c2 38 cc e6"
2✔
238
                                                "0b 29 80 44 a7 1e 21 9c 56 cc 77 b0 51 7f e9 b9 3c 7a 4b fc 44"
239
                                                "d8 7f 38 f8 03 38 ac 98 fc 46 de b3 84 bd 1c ae ac ab 68 67 d7"
240
                                                "26 c4 05 46"),
241
                       Botan::hex_decode_locked("14 00 00 20 a8 ec 43 6d 67 76 34 ae 52 5a c1"
1✔
242
                                                "fc eb e1 1a 03 9e c1 76 94 fa c6 e9 85 27 b6 42 f2 ed d5 ce 61"
243
                                                "16" /* to-be-encrypted content type */));
1✔
244

245
   // encrypted with server_application_traffic_secret
246
   const auto encrypted_new_session_ticket =
1✔
247
      RFC8448_TestData("encrypted_new_session_ticket",
248
                       Connection_Side::Server,
249
                       Botan::hex_decode("17 03 03 00 de"),
2✔
250
                       Botan::hex_decode_locked("3a 6b 8f 90 41 4a 97"
2✔
251
                                                "d6 95 9c 34 87 68 0d e5 13 4a 2b 24 0e 6c ff ac 11 6e 95 d4 1d"
252
                                                "6a f8 f6 b5 80 dc f3 d1 1d 63 c7 58 db 28 9a 01 59 40 25 2f 55"
253
                                                "71 3e 06 1d c1 3e 07 88 91 a3 8e fb cf 57 53 ad 8e f1 70 ad 3c"
254
                                                "73 53 d1 6d 9d a7 73 b9 ca 7f 2b 9f a1 b6 c0 d4 a3 d0 3f 75 e0"
255
                                                "9c 30 ba 1e 62 97 2a c4 6f 75 f7 b9 81 be 63 43 9b 29 99 ce 13"
256
                                                "06 46 15 13 98 91 d5 e4 c5 b4 06 f1 6e 3f c1 81 a7 7c a4 75 84"
257
                                                "00 25 db 2f 0a 77 f8 1b 5a b0 5b 94 c0 13 46 75 5f 69 23 2c 86"
258
                                                "51 9d 86 cb ee ac 87 aa c3 47 d1 43 f9 60 5d 64 f6 50 db 4d 02"
259
                                                "3e 70 e9 52 ca 49 fe 51 37 12 1c 74 bc 26 97 68 7e 24 87 46 d6"
260
                                                "df 35 30 05 f3 bc e1 86 96 12 9c 81 53 55 6b 3b 6c 67 79 b3 7b"
261
                                                "f1 59 85 68 4f"),
262
                       Botan::hex_decode_locked("04 00 00 c9 00 00 00 1e fa d6 aa c5 02 00"
1✔
263
                                                "00 00 b2 2c 03 5d 82 93 59 ee 5f f7 af 4e c9 00 00 00 00 26 2a"
264
                                                "64 94 dc 48 6d 2c 8a 34 cb 33 fa 90 bf 1b 00 70 ad 3c 49 88 83"
265
                                                "c9 36 7c 09 a2 be 78 5a bc 55 cd 22 60 97 a3 a9 82 11 72 83 f8"
266
                                                "2a 03 a1 43 ef d3 ff 5d d3 6d 64 e8 61 be 7f d6 1d 28 27 db 27"
267
                                                "9c ce 14 50 77 d4 54 a3 66 4d 4e 6d a4 d2 9e e0 37 25 a6 a4 da"
268
                                                "fc d0 fc 67 d2 ae a7 05 29 51 3e 3d a2 67 7f a5 90 6c 5b 3f 7d"
269
                                                "8f 92 f2 28 bd a4 0d da 72 14 70 f9 fb f2 97 b5 ae a6 17 64 6f"
270
                                                "ac 5c 03 27 2e 97 07 27 c6 21 a7 91 41 ef 5f 7d e6 50 5e 5b fb"
271
                                                "c3 88 e9 33 43 69 40 93 93 4a e4 d3 57 00 08 00 2a 00 04 00 00"
272
                                                "04 00"
273
                                                "16" /* to-be-encrypted content type */));
1✔
274

275
   // encrypted with client_application_traffic_secret
276
   const auto encrypted_application_data_client =
1✔
277
      RFC8448_TestData("encrypted_application_data_client",
278
                       Connection_Side::Client,
279
                       Botan::hex_decode("17 03 03 00 43"),
2✔
280
                       Botan::hex_decode_locked("a2 3f 70 54 b6 2c 94"
2✔
281
                                                "d0 af fa fe 82 28 ba 55 cb ef ac ea 42 f9 14 aa 66 bc ab 3f 2b"
282
                                                "98 19 a8 a5 b4 6b 39 5b d5 4a 9a 20 44 1e 2b 62 97 4e 1f 5a 62"
283
                                                "92 a2 97 70 14 bd 1e 3d ea e6 3a ee bb 21 69 49 15 e4"),
284
                       Botan::hex_decode_locked("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e"
1✔
285
                                                "0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23"
286
                                                "24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31"
287
                                                "17" /* to-be-encrypted content type */));
1✔
288

289
   // encrypted with server_application_traffic_secret
290
   const auto encrypted_application_data_server =
1✔
291
      RFC8448_TestData("encrypted_application_data_server",
292
                       Connection_Side::Server,
293
                       Botan::hex_decode("17 03 03 00 43"),
2✔
294
                       Botan::hex_decode_locked("2e 93 7e 11 ef 4a c7"
2✔
295
                                                "40 e5 38 ad 36 00 5f c4 a4 69 32 fc 32 25 d0 5f 82 aa 1b 36 e3"
296
                                                "0e fa f9 7d 90 e6 df fc 60 2d cb 50 1a 59 a8 fc c4 9c 4b f2 e5"
297
                                                "f0 a2 1c 00 47 c2 ab f3 32 54 0d d0 32 e1 67 c2 95 5d"),
298
                       Botan::hex_decode_locked("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e"
1✔
299
                                                "0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23"
300
                                                "24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31"
301
                                                "17" /* to-be-encrypted content type */));
1✔
302

303
   auto cipher = Ciphersuite::from_name("AES_128_GCM_SHA256").value();
1✔
304

305
   // initialize Cipher_State with client_hello...server_hello
306
   Journaling_Secret_Logger sl_client;
1✔
307
   Journaling_Secret_Logger sl_server;
1✔
308
   auto cs_client = Cipher_State::init_with_server_hello(
1✔
309
      Connection_Side::Client, secure_vector<uint8_t>(shared_secret), cipher, th_server_hello, sl_client);
1✔
310
   auto cs_server = Cipher_State::init_with_server_hello(
1✔
311
      Connection_Side::Server, secure_vector<uint8_t>(shared_secret), cipher, th_server_hello, sl_server);
1✔
312

313
   auto CHECK_both = make_CHECK_both(cs_client.get(), &sl_client, cs_server.get(), &sl_server);
1✔
314

315
   return Test::flatten_result_lists(
8✔
316
      {CHECK_both(
1✔
317
          "secret logging during initialization",
318
          [&](Cipher_State*, Journaling_Secret_Logger* sl, Connection_Side, Test::Result& result) {
2✔
319
             result.test_eq("logged expected secrets", sl->secrets.size(), 2);
2✔
320
             result.require("has client traffic secret", sl->secrets.contains("CLIENT_HANDSHAKE_TRAFFIC_SECRET"));
4✔
321
             result.require("has server traffic secret", sl->secrets.contains("SERVER_HANDSHAKE_TRAFFIC_SECRET"));
4✔
322

323
             result.test_is_eq("client traffic secret",
4✔
324
                               sl->secrets.at("CLIENT_HANDSHAKE_TRAFFIC_SECRET"),
2✔
325
                               client_handshake_traffic_secret);
326
             result.test_is_eq("server traffic secret",
4✔
327
                               sl->secrets.at("SERVER_HANDSHAKE_TRAFFIC_SECRET"),
2✔
328
                               server_handshake_traffic_secret);
329
          }),
2✔
330

331
       CHECK_both("ciphersuite compatibility",
1✔
332
                  [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side side, Test::Result& result) {
2✔
333
                     result.confirm("self-compatibility", cs->is_compatible_with(cipher));
4✔
334
                     result.confirm(
4✔
335
                        "fully defined state is not compatible to other suites",
336
                        !cs->is_compatible_with(Ciphersuite::from_name("CHACHA20_POLY1305_SHA256").value()) &&
6✔
337
                           !cs->is_compatible_with(Ciphersuite::from_name("AES_128_CCM_SHA256").value()) &&
6✔
338
                           !cs->is_compatible_with(Ciphersuite::from_name("PSK_WITH_AES_128_GCM_SHA256").value()));
4✔
339
                     if(side == Connection_Side::Client) {
2✔
340
                        result.confirm("Clients don't expect unprotected alerts after server hello",
1✔
341
                                       !cs->must_expect_unprotected_alert_traffic());
1✔
342
                     } else {
343
                        result.confirm("Servers must expect unprotected alerts in response to their server hello",
2✔
344
                                       cs->must_expect_unprotected_alert_traffic());
1✔
345
                     }
346
                  }),
2✔
347

348
       CHECK_both("ticket nonce counter is not yet available",
1✔
349
                  [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) {
2✔
350
                     result.test_throws<Botan::Invalid_State>("nonce counter is disabled",
4✔
351
                                                              [&] { cs->next_ticket_nonce(); });
4✔
352
                  }),
2✔
353

354
       CHECK_both("handshake traffic without PSK",
1✔
355
                  [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) {
2✔
356
                     result.confirm("can not yet write application data", !cs->can_encrypt_application_traffic());
4✔
357
                     result.confirm("can not yet export key material", !cs->can_export_keys());
6✔
358

359
                     // decrypt encrypted extensions from server
360
                     encrypted_extensions.xxcrypt(result, cs, side);
2✔
361

362
                     // validate the MAC we receive in server Finished message
363
                     const auto expected_server_mac = Botan::hex_decode(
2✔
364
                        "9b 9b 14 1d 90 63 37 fb d2 cb dc e7 1d f4"
365
                        "de da 4a b4 2c 30 95 72 cb 7f ff ee 54 54 b7 8f 07 18");
2✔
366
                     if(side == Connection_Side::Client) {
2✔
367
                        result.confirm("expecting the correct MAC for server finished",
2✔
368
                                       cs->verify_peer_finished_mac(th_pre_server_finished, expected_server_mac));
1✔
369
                     } else {
370
                        result.test_eq("expecting the correct MAC for server finished",
2✔
371
                                       cs->finished_mac(th_pre_server_finished),
2✔
372
                                       expected_server_mac);
373
                     }
374

375
                     // advance Cipher_State with client_hello...server_Finished
376
                     // (allows receiving of application data, but does not yet allow such sending)
377
                     result.test_no_throw("state advancement is legal",
4✔
378
                                          [&] { cs->advance_with_server_finished(th_server_finished, *sl); });
4✔
379

380
                     if(side == Connection_Side::Client) {
2✔
381
                        result.confirm("can read application data", cs->can_decrypt_application_traffic());
2✔
382
                        result.confirm("can not yet write application data", !cs->can_encrypt_application_traffic());
2✔
383
                        result.confirm("Clients don't expect unprotected alerts after server hello",
1✔
384
                                       !cs->must_expect_unprotected_alert_traffic());
1✔
385
                     } else {
386
                        result.confirm("can not yet read application data", !cs->can_decrypt_application_traffic());
2✔
387
                        result.confirm("can write application data", cs->can_encrypt_application_traffic());
2✔
388
                        result.confirm("Servers must expect unprotected alerts in response to their first flight",
2✔
389
                                       cs->must_expect_unprotected_alert_traffic());
1✔
390
                     }
391

392
                     // check the logged key material
393
                     result.test_eq("contains expected number of keys", sl->secrets.size(), 5);
2✔
394
                     result.require("has client traffic secret", sl->secrets.contains("CLIENT_TRAFFIC_SECRET_0"));
4✔
395
                     result.require("has server traffic secret", sl->secrets.contains("SERVER_TRAFFIC_SECRET_0"));
4✔
396
                     result.require("has exporter secret", sl->secrets.contains("EXPORTER_SECRET"));
4✔
397
                     result.test_eq(
6✔
398
                        "client traffic secret (0)", sl->secrets.at("CLIENT_TRAFFIC_SECRET_0"), client_traffic_secret);
2✔
399
                     result.test_eq(
6✔
400
                        "server traffic secret (0)", sl->secrets.at("SERVER_TRAFFIC_SECRET_0"), server_traffic_secret);
2✔
401

402
                     // generate the MAC for the client Finished message
403
                     const auto expected_client_mac = Botan::hex_decode(
2✔
404
                        "a8 ec 43 6d 67 76 34 ae 52 5a c1 fc eb e1 1a 03"
405
                        "9e c1 76 94 fa c6 e9 85 27 b6 42 f2 ed d5 ce 61");
2✔
406
                     if(side == Connection_Side::Client) {
2✔
407
                        result.test_eq("generating the correct MAC for client finished",
2✔
408
                                       cs->finished_mac(th_server_finished),
2✔
409
                                       expected_client_mac);
410
                     } else {
411
                        result.confirm("verify the correct MAC for client finished",
2✔
412
                                       cs->verify_peer_finished_mac(th_server_finished, expected_client_mac));
1✔
413
                     }
414

415
                     // encrypt client Finished message by client
416
                     // (under the client handshake traffic secret)
417
                     encrypted_client_finished_message.xxcrypt(result, cs, side);
2✔
418

419
                     // advance Cipher_State with client_hello...client_Finished
420
                     // (allows generation of resumption PSKs)
421
                     result.test_no_throw("state advancement is legal",
4✔
422
                                          [&] { cs->advance_with_client_finished(th_client_finished); });
4✔
423

424
                     result.confirm("can write application data", cs->can_encrypt_application_traffic());
4✔
425
                     result.confirm("can read application data", cs->can_decrypt_application_traffic());
4✔
426
                     result.confirm("doesn't need to expect unprotected alerts",
2✔
427
                                    !cs->must_expect_unprotected_alert_traffic());
2✔
428
                     result.confirm("can export key material", cs->can_export_keys());
6✔
429
                     result.test_eq("key export produces expected result",
4✔
430
                                    cs->export_key(export_label, export_context, 16),
2✔
431
                                    expected_key_export);
432

433
                     // decrypt "new session ticket" post-handshake message from server
434
                     // (encrypted under the application traffic secret)
435
                     encrypted_new_session_ticket.xxcrypt(result, cs, side);
2✔
436

437
                     // encrypt application data by client
438
                     encrypted_application_data_client.xxcrypt(result, cs, side);
2✔
439

440
                     // decrypt application data from server
441
                     // (encrypted under the application traffic secret -- and a new sequence number)
442
                     encrypted_application_data_server.xxcrypt(result, cs, side);
2✔
443

444
                     result.confirm("can export key material still", cs->can_export_keys());
6✔
445
                     result.test_eq("key export result did not change",
4✔
446
                                    cs->export_key(export_label, export_context, 16),
4✔
447
                                    expected_key_export);
448
                  }),
4✔
449

450
       CHECK_both("ticket nonce counter counts",
1✔
451
                  [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) {
2✔
452
                     result.test_is_eq("nonce is 0x00, 0x00",
4✔
453
                                       cs->next_ticket_nonce(),
2✔
454
                                       Botan::TLS::Ticket_Nonce(std::vector<uint8_t>{0x00, 0x00}));
4✔
455
                     result.test_is_eq("nonce is 0x00, 0x01",
4✔
456
                                       cs->next_ticket_nonce(),
2✔
457
                                       Botan::TLS::Ticket_Nonce(std::vector<uint8_t>{0x00, 0x01}));
4✔
458
                     result.test_is_eq("nonce is 0x00, 0x02",
4✔
459
                                       cs->next_ticket_nonce(),
2✔
460
                                       Botan::TLS::Ticket_Nonce(std::vector<uint8_t>{0x00, 0x02}));
4✔
461

462
                     for(uint32_t i = 3; i < std::numeric_limits<uint16_t>::max(); ++i) {
131,066✔
463
                        cs->next_ticket_nonce();
262,128✔
464
                     }
465

466
                     // Cannot generate more than 2^16 ticket nonces
467
                     result.test_throws<Botan::Invalid_State>("nonces are depleted", [&] { cs->next_ticket_nonce(); });
6✔
468
                  }),
2✔
469

470
       CHECK_both("PSK",
1✔
471
                  [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) {
2✔
472
                     // derive PSK for resumption
473
                     const auto psk = cs->psk(Botan::TLS::Ticket_Nonce(
2✔
474
                        std::vector<uint8_t>{0x00, 0x00}) /* ticket_nonce as defined in RFC 8448 */);
2✔
475
                     result.test_eq("PSK matches", psk, expected_psk);
4✔
476
                  }),
2✔
477

478
       CHECK_both("key update",
1✔
479
                  [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) {
2✔
480
                     const auto read_label =
2✔
481
                        side == Connection_Side::Client ? "SERVER_TRAFFIC_SECRET_1" : "CLIENT_TRAFFIC_SECRET_1";
482
                     const auto write_label =
1✔
483
                        side == Connection_Side::Client ? "CLIENT_TRAFFIC_SECRET_1" : "SERVER_TRAFFIC_SECRET_1";
484

485
                     cs->update_read_keys(*sl);
2✔
486
                     result.test_eq("read secret update is here", sl->secrets.size(), 6);
2✔
487
                     result.require("has new read traffic secret", sl->secrets.contains(read_label));
4✔
488

489
                     cs->update_write_keys(*sl);
2✔
490
                     result.test_eq("write secret update is here", sl->secrets.size(), 7);
2✔
491
                     result.require("has new write traffic secret", sl->secrets.contains(write_label));
4✔
492

493
                     result.test_eq("client traffic secret (1)",
6✔
494
                                    sl->secrets.at("CLIENT_TRAFFIC_SECRET_1"),
2✔
495
                                    updated_client_traffic_secret);
496
                     result.test_eq("server traffic secret (1)",
6✔
497
                                    sl->secrets.at("SERVER_TRAFFIC_SECRET_1"),
2✔
498
                                    updated_server_traffic_secret);
499

500
                     result.confirm("can encrypt application traffic", cs->can_encrypt_application_traffic());
4✔
501
                  }),
2✔
502

503
       CHECK_both("cleanup", [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) {
1✔
504
          // cleanup
505
          cs->clear_write_keys();
2✔
506
          result.confirm("can no longer write application data", !cs->can_encrypt_application_traffic());
4✔
507
          result.confirm("can still read application data", cs->can_decrypt_application_traffic());
4✔
508

509
          cs->clear_read_keys();
2✔
510
          result.confirm("can no longer write application data", !cs->can_encrypt_application_traffic());
4✔
511
          result.confirm("can no longer read application data", !cs->can_decrypt_application_traffic());
4✔
512
       })});
11✔
513
}
18✔
514

515
std::vector<Test::Result> test_secret_derivation_rfc8448_rtt0() {
1✔
516
   // this is the PSK that was negotiated for session resumption in RFC 8448 (see test case above)
517
   const auto psk = Botan::hex_decode_locked(
1✔
518
      "4e cd 0e b6 ec 3b 4d 87 f5 d6 02 8f 92 2c a4 c5"
519
      "85 1a 27 7f d4 13 11 c9 e6 2d 2c 94 92 e1 c4 f3");
1✔
520

521
   // this shared secret is obtained by a key exchange performed additionally to
522
   // the pre-shared-key.
523
   const auto shared_secret = Botan::hex_decode_locked(
1✔
524
      "f4 41 94 75 6f f9 ec 9d 25 18 06 35 d6 6e a6 82"
525
      "4c 6a b3 bf 17 99 77 be 37 f7 23 57 0e 7c cb 2e");
1✔
526

527
   // transcript hash of the client hello up to (including) the PSK modes
528
   // (used to calculate the PSK binder)
529
   const auto th_client_hello_prefix = Botan::hex_decode(
1✔
530
      "63 22 4b 2e 45 73 f2 d3 45 4c a8 4b 9d 00 9a 04"
531
      "f6 be 9e 05 71 1a 83 96 47 3a ef a0 1e 92 4a 14");
1✔
532

533
   // transcript hash of the client hello including the PSK identity and binders
534
   const auto th_client_hello = Botan::hex_decode(
1✔
535
      "08 ad 0f a0 5d 7c 72 33 b1 77 5b a2 ff 9f 4c 5b"
536
      "8b 59 27 6b 7f 22 7f 13 a9 76 24 5f 5d 96 09 13");
1✔
537

538
   const auto th_server_hello = Botan::hex_decode(
1✔
539
      "f7 36 cb 34 fe 25 e7 01 55 1b ee 6f d2 4c 1c c7"
540
      "10 2a 7d af 94 05 cb 15 d9 7a af e1 6f 75 7d 03");
1✔
541

542
   // this is not directly exposed in RFC 8448 but calculated as
543
   // SHA-256(ClientHello..EncryptedExtensions)
544
   const auto th_pre_server_finished = Botan::hex_decode(
1✔
545
      "04 05 54 55 ef 74 b2 32 2b a3 66 cb c4 cf e0 27"
546
      "23 43 4b 37 b9 b3 67 1b b5 a3 00 60 56 d8 f0 2f");
1✔
547

548
   const auto th_server_finished = Botan::hex_decode(
1✔
549
      "b0 ae ff c4 6a 2c fe 33 11 4e 6f d7 d5 1f 9f 04"
550
      "b1 ca 3c 49 7d ab 08 93 4a 77 4a 9d 9a d7 db f3");
1✔
551

552
   // this is not directly exposed in RFC 8448 but calculated as
553
   // SHA-256(ClientHello..EndOfEarlyData)
554
   const auto th_end_of_early_data = Botan::hex_decode(
1✔
555
      "9f 23 a0 0c 1f 08 fc 18 80 7b 8b 68 23 7b 56 5d"
556
      "f2 0d 4c 50 dd 8e 49 ef 61 2e 1a 5b b1 6c 58 67");
1✔
557

558
   const auto th_client_finished = Botan::hex_decode(
1✔
559
      "c3 c1 22 e0 bd 90 7a 4a 3f f6 11 2d 8f d5 3d bf"
560
      "89 c7 73 d9 55 2e 8b 6b 9d 56 d3 61 b3 a9 7b f6");
1✔
561

562
   const auto expected_psk_binder = Botan::hex_decode(
1✔
563
      "3a dd 4f b2 d8 fd f8 22 a0 ca 3c f7 67 8e f5 e8"
564
      "8d ae 99 01 41 c5 92 4d 57 bb 6f a3 1b 9e 5f 9d");
1✔
565

566
   const auto early_exporter_secret = Botan::hex_decode(
1✔
567
      "b2 02 68 66 61 09 37 d7 42 3e 5b e9 08 62 cc f2"
568
      "4c 0e 60 91 18 6d 34 f8 12 08 9f f5 be 2e f7 df");
1✔
569

570
   const auto client_handshake_traffic_secret = Botan::hex_decode(
1✔
571
      "2f aa c0 8f 85 1d 35 fe a3 60 4f cb 4d e8 2d c6"
572
      "2c 9b 16 4a 70 97 4d 04 62 e2 7f 1a b2 78 70 0f");
1✔
573

574
   const auto server_handshake_traffic_secret = Botan::hex_decode(
1✔
575
      "fe 92 7a e2 71 31 2e 8b f0 27 5b 58 1c 54 ee f0"
576
      "20 45 0d c4 ec ff aa 05 a1 a3 5d 27 51 8e 78 03");
1✔
577

578
   const auto client_traffic_secret = Botan::hex_decode(
1✔
579
      "2a bb f2 b8 e3 81 d2 3d be be 1d d2 a7 d1 6a 8b"
580
      "f4 84 cb 49 50 d2 3f b7 fb 7f a8 54 70 62 d9 a1");
1✔
581

582
   const auto server_traffic_secret = Botan::hex_decode(
1✔
583
      "cc 21 f1 bf 8f eb 7d d5 fa 50 5b d9 c4 b4 68 a9"
584
      "98 4d 55 4a 99 3d c4 9e 6d 28 55 98 fb 67 26 91");
1✔
585

586
   const auto exporter_secret = Botan::hex_decode(
1✔
587
      "3f d9 3d 4f fd dc 98 e6 4b 14 dd 10 7a ed f8 ee"
588
      "4a dd 23 f4 51 0f 58 a4 59 2d 0b 20 1b ee 56 b4");
1✔
589

590
   // this is not part of RFC 8448
591
   const std::string export_label = "export_test_label";
1✔
592
   const std::string export_context = "rfc8448_psk";
1✔
593
   const auto expected_key_export = Botan::hex_decode_locked("b5 89 bc b4 0b 7f 94 d7 6f 2d d6 fc f9 e5 87 8e");
1✔
594

595
   // this is not part of RFC 8448
596
   const std::string early_export_label = "export_test_label_early";
1✔
597
   const std::string early_export_context = "rfc8448_psk_early";
1✔
598
   const auto early_expected_key_export = Botan::hex_decode_locked("b6 fb 7d 9e b5 4e 97 59 6f e4 ed 93 cc b0 bf 0c");
1✔
599

600
   // encrypted with server_handshake_traffic_secret
601
   const auto encrypted_extensions =
1✔
602
      RFC8448_TestData("encrypted_extensions",
603
                       Connection_Side::Server,
604
                       Botan::hex_decode("17 03 03 00 61"),
2✔
605
                       Botan::hex_decode_locked("dc 48 23 7b 4b 87 9f"
2✔
606
                                                "50 d0 d4 d2 62 ea 8b 47 16 eb 40 dd c1 eb 95 7e 11 12 6e 8a 71"
607
                                                "49 c2 d0 12 d3 7a 71 15 95 7e 64 ce 30 00 8b 9e 03 23 f2 c0 5a"
608
                                                "9c 1c 77 b4 f3 78 49 a6 95 ab 25 50 60 a3 3f ee 77 0c a9 5c b8"
609
                                                "48 6b fd 08 43 b8 70 24 86 5c a3 5c c4 1c 4e 51 5c 64 dc b1 36"
610
                                                "9f 98 63 5b c7 a5"),
611
                       Botan::hex_decode_locked("08 00 00 28 00 26 00 0a 00 14 00 12 00 1d 00"
1✔
612
                                                "17 00 18 00 19 01 00 01 01 01 02 01 03 01 04 00 1c 00 02 40 01"
613
                                                "00 00 00 00 00 2a 00 00 14 00 00 20 48 d3 e0 e1 b3 d9 07 c6 ac"
614
                                                "ff 14 5e 16 09 03 88 c7 7b 05 c0 50 b6 34 ab 1a 88 bb d0 dd 1a"
615
                                                "34 b2"
616
                                                "16" /* to-be-encrypted content type */));
1✔
617

618
   // encrypted with client_handshake_traffic_secret
619
   const auto encrypted_client_finished_message =
1✔
620
      RFC8448_TestData("encrypted_client_finished_message",
621
                       Connection_Side::Client,
622
                       Botan::hex_decode("17 03 03 00 35"),
2✔
623
                       Botan::hex_decode_locked("00 f8 b4 67 d1 4c f2"
2✔
624
                                                "2a 4b 3f 0b 6a e0 d8 e6 cc 8d 08 e0 db 35 15 ef 5c 2b df 19 22"
625
                                                "ea fb b7 00 09 96 47 16 d8 34 fb 70 c3 d2 a5 6c 5b 1f 5f 6b db"
626
                                                "a6 c3 33 cf"),
627
                       Botan::hex_decode_locked("14 00 00 20 72 30 a9 c9 52 c2 5c d6 13 8f"
1✔
628
                                                "c5 e6 62 83 08 c4 1c 53 35 dd 81 b9 f9 6b ce a5 0f d3 2b da 41 6d"
629
                                                "16" /* to-be-encrypted content type */));
1✔
630

631
   // encrypted with client_application_traffic_secret
632
   const auto encrypted_application_data_client =
1✔
633
      RFC8448_TestData("encrypted_application_data_client",
634
                       Connection_Side::Client,
635
                       Botan::hex_decode("17 03 03 00 43"),
2✔
636
                       Botan::hex_decode_locked("b1 ce bc e2 42 aa 20"
2✔
637
                                                "1b e9 ae 5e 1c b2 a9 aa 4b 33 d4 e8 66 af 1e db 06 89 19 23 77"
638
                                                "41 aa 03 1d 7a 74 d4 91 c9 9b 9d 4e 23 2b 74 20 6b c6 fb aa 04"
639
                                                "fe 78 be 44 a9 b4 f5 43 20 a1 7e b7 69 92 af ac 31 03"),
640
                       Botan::hex_decode_locked("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e"
1✔
641
                                                "0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23"
642
                                                "24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31"
643
                                                "17" /* to-be-encrypted content type */));
1✔
644

645
   // encrypted with server_application_traffic_secret
646
   const auto encrypted_application_data_server =
1✔
647
      RFC8448_TestData("encrypted_application_data_server",
648
                       Connection_Side::Server,
649
                       Botan::hex_decode("17 03 03 00 43"),
2✔
650
                       Botan::hex_decode_locked("27 5e 9f 20 ac ff 57"
2✔
651
                                                "bc 00 06 57 d3 86 7d f0 39 cc cf 79 04 78 84 cf 75 77 17 46 f7"
652
                                                "40 b5 a8 3f 46 2a 09 54 c3 58 13 93 a2 03 a2 5a 7d d1 41 41 ef"
653
                                                "1a 37 90 0c db 62 ff 62 de e1 ba 39 ab 25 90 cb f1 94"),
654
                       Botan::hex_decode_locked("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e"
1✔
655
                                                "0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23"
656
                                                "24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31"
657
                                                "17" /* to-be-encrypted content type */));
1✔
658

659
   auto cipher = Ciphersuite::from_name("AES_128_GCM_SHA256").value();
1✔
660

661
   Journaling_Secret_Logger sl_client;
1✔
662
   Journaling_Secret_Logger sl_server;
1✔
663

664
   auto cs_client = Cipher_State::init_with_psk(Connection_Side::Client,
1✔
665
                                                Cipher_State::PSK_Type::Resumption,
666
                                                secure_vector<uint8_t>(psk.begin(), psk.end()),
2✔
667
                                                cipher.prf_algo());
1✔
668
   auto cs_server = Cipher_State::init_with_psk(Connection_Side::Server,
1✔
669
                                                Cipher_State::PSK_Type::Resumption,
670
                                                secure_vector<uint8_t>(psk.begin(), psk.end()),
2✔
671
                                                cipher.prf_algo());
1✔
672

673
   auto CHECK_both = make_CHECK_both(cs_client.get(), &sl_client, cs_server.get(), &sl_server);
1✔
674

675
   return Test::flatten_result_lists(
6✔
676
      {CHECK_both("no secrets logged for PSK initialization",
1✔
677
                  [&](Cipher_State*, Journaling_Secret_Logger* sl, Connection_Side, Test::Result& result) {
2✔
678
                     result.test_eq("no secrets logged", sl->secrets.size(), 0);
2✔
679
                  }),
2✔
680

681
       CHECK_both("calculating PSK binder",
1✔
682
                  [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) {
2✔
683
                     const auto mac = cs->psk_binder_mac(th_client_hello_prefix);
2✔
684
                     result.test_eq("PSK binder is as expected", mac, expected_psk_binder);
4✔
685
                  }),
2✔
686

687
       CHECK_both(
1✔
688
          "ciphersuite compatibility",
689
          [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side, Test::Result& result) {
2✔
690
             result.confirm("self-compatibility", cs->is_compatible_with(cipher));
4✔
691
             result.confirm("partially defined state is compatible with suites using the same hash",
4✔
692
                            cs->is_compatible_with(Ciphersuite::from_name("CHACHA20_POLY1305_SHA256").value()) &&
6✔
693
                               cs->is_compatible_with(Ciphersuite::from_name("AES_128_CCM_SHA256").value()) &&
6✔
694
                               cs->is_compatible_with(Ciphersuite::from_name("AES_128_CCM_8_SHA256").value()));
4✔
695

696
             result.confirm("partially defined state is not compatible with other hashes or protocol versions",
4✔
697
                            !cs->is_compatible_with(Ciphersuite::from_name("PSK_WITH_AES_128_GCM_SHA256").value()) &&
6✔
698
                               !cs->is_compatible_with(Ciphersuite::from_name("AES_256_GCM_SHA384").value()));
4✔
699
          }),
2✔
700

701
       CHECK_both("calculate the early traffic secrets",
1✔
702
                  [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) {
2✔
703
                     cs->advance_with_client_hello(th_client_hello, *sl);
2✔
704
                     result.require("early key export is possible", cs->can_export_keys());
4✔
705
                     result.test_eq("early key export produces expected result",
4✔
706
                                    cs->export_key(early_export_label, early_export_context, 16),
2✔
707
                                    early_expected_key_export);
708

709
                     if(side == Connection_Side::Client) {
2✔
710
                        result.confirm("Clients must expect servers to respond with an unprotected alert",
2✔
711
                                       cs->must_expect_unprotected_alert_traffic());
1✔
712
                     } else {
713
                        result.confirm(
1✔
714
                           "Servers do not expect clients to send alerts protected with the early data secret",
715
                           !cs->must_expect_unprotected_alert_traffic());
1✔
716
                     }
717

718
                     result.test_eq("logged early secrets", sl->secrets.size(), 1);
2✔
719
                     result.require("has early exporter secret", sl->secrets.contains("EARLY_EXPORTER_MASTER_SECRET"));
4✔
720
                     result.test_eq(
6✔
721
                        "early exporter secret", sl->secrets.at("EARLY_EXPORTER_MASTER_SECRET"), early_exporter_secret);
2✔
722

723
                     // TODO: Once 0-RTT traffic is implemented this will likely allow handling of
724
                     //       application traffic in this state.
725
                     result.confirm("can not yet write application data", !cs->can_encrypt_application_traffic());
4✔
726
                     result.confirm("can not yet read application data", !cs->can_decrypt_application_traffic());
4✔
727
                  }),
2✔
728

729
       CHECK_both(
1✔
730
          "handshake traffic after PSK",
731
          [&](Cipher_State* cs, Journaling_Secret_Logger* sl, Connection_Side side, Test::Result& result) {
2✔
732
             cs->advance_with_server_hello(cipher, secure_vector<uint8_t>(shared_secret), th_server_hello, *sl);
2✔
733

734
             // decrypt encrypted extensions from server
735
             encrypted_extensions.xxcrypt(result, cs, side);
2✔
736

737
             // check the logged key material
738
             result.test_eq("contains expected number of keys", sl->secrets.size(), 3);
2✔
739
             result.require("has client handshake traffic secret",
4✔
740
                            sl->secrets.contains("CLIENT_HANDSHAKE_TRAFFIC_SECRET"));
2✔
741
             result.require("has server handshake traffic secret",
4✔
742
                            sl->secrets.contains("SERVER_HANDSHAKE_TRAFFIC_SECRET"));
2✔
743
             result.test_eq("client handshake traffic secret",
6✔
744
                            sl->secrets.at("CLIENT_HANDSHAKE_TRAFFIC_SECRET"),
2✔
745
                            client_handshake_traffic_secret);
746
             result.test_eq("server handshake traffic secret",
6✔
747
                            sl->secrets.at("SERVER_HANDSHAKE_TRAFFIC_SECRET"),
2✔
748
                            server_handshake_traffic_secret);
749

750
             // TODO: Handling of early traffic is left out as 0-RTT is not implemented yet.
751

752
             // validate the MAC we receive in server Finished message
753
             const auto expected_server_mac = Botan::hex_decode(
2✔
754
                "48 d3 e0 e1 b3 d9 07 c6 ac ff 14 5e 16 09 03 88"
755
                "c7 7b 05 c0 50 b6 34 ab 1a 88 bb d0 dd 1a 34 b2");
2✔
756
             if(side == Connection_Side::Client) {
2✔
757
                result.confirm("expecting the correct MAC for server finished",
2✔
758
                               cs->verify_peer_finished_mac(th_pre_server_finished, expected_server_mac));
1✔
759
                result.confirm("Clients don't expect unprotected alerts after server hello",
1✔
760
                               !cs->must_expect_unprotected_alert_traffic());
1✔
761
             } else {
762
                result.test_eq("expecting the correct MAC for server finished",
2✔
763
                               cs->finished_mac(th_pre_server_finished),
1✔
764
                               expected_server_mac);
765
                result.confirm("Servers must expect unprotected alerts in response to their server hello",
2✔
766
                               cs->must_expect_unprotected_alert_traffic());
1✔
767
             }
768

769
             result.confirm("cannot read application data", !cs->can_decrypt_application_traffic());
4✔
770
             result.confirm("cannot write application data", !cs->can_encrypt_application_traffic());
4✔
771

772
             // advance Cipher_State with client_hello...server_Finished
773
             // (allows receiving of application data, but no such sending)
774
             result.test_no_throw("state advancement is legal",
4✔
775
                                  [&] { cs->advance_with_server_finished(th_server_finished, *sl); });
4✔
776

777
             if(side == Connection_Side::Client) {
2✔
778
                result.confirm("can read application data", cs->can_decrypt_application_traffic());
2✔
779
                result.confirm("cannot write application data", !cs->can_encrypt_application_traffic());
2✔
780
                result.confirm("Clients don't expect unprotected alerts after server hello",
1✔
781
                               !cs->must_expect_unprotected_alert_traffic());
1✔
782
             } else {
783
                result.confirm("cannot read application data", !cs->can_decrypt_application_traffic());
2✔
784
                result.confirm("can write application data", cs->can_encrypt_application_traffic());
2✔
785
                result.confirm("Servers must expect unprotected alerts in response to their first flight",
2✔
786
                               cs->must_expect_unprotected_alert_traffic());
1✔
787
             }
788

789
             // check the logged key material
790
             result.test_eq("contains expected number of keys", sl->secrets.size(), 6);
2✔
791
             result.require("has client traffic secret", sl->secrets.contains("CLIENT_TRAFFIC_SECRET_0"));
4✔
792
             result.require("has server traffic secret", sl->secrets.contains("SERVER_TRAFFIC_SECRET_0"));
4✔
793
             result.require("has exporter secret", sl->secrets.contains("EXPORTER_SECRET"));
4✔
794
             result.test_eq("client traffic secret", sl->secrets.at("CLIENT_TRAFFIC_SECRET_0"), client_traffic_secret);
4✔
795
             result.test_eq("server traffic secret", sl->secrets.at("SERVER_TRAFFIC_SECRET_0"), server_traffic_secret);
4✔
796
             result.test_eq("exporter secret", sl->secrets.at("EXPORTER_SECRET"), exporter_secret);
4✔
797

798
             // generate the MAC for the client Finished message
799
             const auto expected_client_mac = Botan::hex_decode(
2✔
800
                "72 30 a9 c9 52 c2 5c d6 13 8f c5 e6 62 83 08 c4"
801
                "1c 53 35 dd 81 b9 f9 6b ce a5 0f d3 2b da 41 6d");
2✔
802
             if(side == Connection_Side::Client) {
2✔
803
                result.test_eq("generating the correct MAC for client finished",
2✔
804
                               cs->finished_mac(th_end_of_early_data),
2✔
805
                               expected_client_mac);
806
             } else {
807
                result.confirm("verify the correct MAC for client finished",
2✔
808
                               cs->verify_peer_finished_mac(th_end_of_early_data, expected_client_mac));
1✔
809
             }
810

811
             // encrypt client Finished message by client
812
             // (under the client handshake traffic secret)
813
             encrypted_client_finished_message.xxcrypt(result, cs, side);
2✔
814
          }),
4✔
815

816
       CHECK_both("application traffic after PSK",
1✔
817
                  [&](Cipher_State* cs, Journaling_Secret_Logger*, Connection_Side side, Test::Result& result) {
2✔
818
                     // advance Cipher_State with client_hello...client_Finished
819
                     // (allows generation of resumption PSKs)
820
                     result.test_no_throw("state advancement is legal",
4✔
821
                                          [&] { cs->advance_with_client_finished(th_client_finished); });
4✔
822

823
                     result.confirm("can read application data", cs->can_decrypt_application_traffic());
4✔
824
                     result.confirm("can write application data", cs->can_encrypt_application_traffic());
4✔
825
                     result.confirm("doesn't need to expect unprotected alerts",
2✔
826
                                    !cs->must_expect_unprotected_alert_traffic());
2✔
827
                     result.confirm("can export key material", cs->can_export_keys());
6✔
828
                     result.test_eq("key export produces expected result",
4✔
829
                                    cs->export_key(export_label, export_context, 16),
2✔
830
                                    expected_key_export);
831

832
                     // encrypt application data by client
833
                     encrypted_application_data_client.xxcrypt(result, cs, side);
2✔
834

835
                     // decrypt application data from server
836
                     // (encrypted under the application traffic secret -- and a new sequence number)
837
                     encrypted_application_data_server.xxcrypt(result, cs, side);
2✔
838
                  })});
9✔
839
}
20✔
840

841
BOTAN_REGISTER_TEST_FN("tls",
842
                       "tls_cipher_state",
843
                       test_secret_derivation_rfc8448_rtt1,
844
                       test_secret_derivation_rfc8448_rtt0);
845
}  // namespace
846

847
}  // namespace Botan_Tests
848

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