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

randombit / botan / 21753596263

06 Feb 2026 02:13PM UTC coverage: 90.063% (-0.01%) from 90.073%
21753596263

Pull #5289

github

web-flow
Merge 587099284 into 8ea0ca252
Pull Request #5289: Further misc header reductions, forward declarations, etc

102237 of 113517 relevant lines covered (90.06%)

11402137.11 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/hex.h>
13
   #include <botan/secmem.h>
14
   #include <botan/tls_ciphersuite.h>
15

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

19
namespace Botan_Tests {
20

21
namespace {
22

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

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

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

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

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

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

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

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

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

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

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

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

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

106
   // this is not part of RFC 8448
107
   const std::string export_label = "export_test_label";
1✔
108
   const std::string export_context = "rfc8448_rtt1";
1✔
109
   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✔
110

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

591
   // this is not part of RFC 8448
592
   const std::string export_label = "export_test_label";
1✔
593
   const std::string export_context = "rfc8448_psk";
1✔
594
   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✔
595

596
   // this is not part of RFC 8448
597
   const std::string early_export_label = "export_test_label_early";
1✔
598
   const std::string early_export_context = "rfc8448_psk_early";
1✔
599
   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✔
600

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

848
}  // namespace Botan_Tests
849

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