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

randombit / botan / 21863608093

10 Feb 2026 11:46AM UTC coverage: 90.064% (-0.004%) from 90.068%
21863608093

Pull #5303

github

web-flow
Merge aea1c629d into 1d119e57a
Pull Request #5303: Refactor: Organize TLS Extensions into TLS 1.2 and 1.3 Modules

102231 of 113509 relevant lines covered (90.06%)

11483899.99 hits per line

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

99.26
/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
   #include <map>
19

20
   #include <map>
21

22
namespace Botan_Tests {
23

24
namespace {
25

26
using namespace Botan;
27
using namespace Botan::TLS;
28

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

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

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

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

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

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

79
         result.test_eq("encrypted payload for " + name, plaintext_fragment_copy, encrypted_fragment);
18✔
80
      }
9✔
81

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

87
         result.test_eq("plaintext for " + name, encrypted_fragment_copy, plaintext_fragment);
18✔
88
      }
9✔
89

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

307
   auto cipher = Ciphersuite::from_name("AES_128_GCM_SHA256").value();
1✔
308

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

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

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

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

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

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

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

363
                     // decrypt encrypted extensions from server
364
                     encrypted_extensions.xxcrypt(result, cs, side);
2✔
365

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

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

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

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

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

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

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

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

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

441
                     // encrypt application data by client
442
                     encrypted_application_data_client.xxcrypt(result, cs, side);
2✔
443

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

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

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

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

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

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

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

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

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

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

504
                     result.confirm("can encrypt application traffic", cs->can_encrypt_application_traffic());
4✔
505
                  }),
2✔
506

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

663
   auto cipher = Ciphersuite::from_name("AES_128_GCM_SHA256").value();
1✔
664

665
   Journaling_Secret_Logger sl_client;
1✔
666
   Journaling_Secret_Logger sl_server;
1✔
667

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

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

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

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

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

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

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

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

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

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

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

738
             // decrypt encrypted extensions from server
739
             encrypted_extensions.xxcrypt(result, cs, side);
2✔
740

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

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

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

773
             result.confirm("cannot read application data", !cs->can_decrypt_application_traffic());
4✔
774
             result.confirm("cannot write application data", !cs->can_encrypt_application_traffic());
4✔
775

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

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

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

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

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

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

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

836
                     // encrypt application data by client
837
                     encrypted_application_data_client.xxcrypt(result, cs, side);
2✔
838

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

845
BOTAN_REGISTER_TEST_FN("tls",
846
                       "tls_cipher_state",
847
                       test_secret_derivation_rfc8448_rtt1,
848
                       test_secret_derivation_rfc8448_rtt0);
849
}  // namespace
850

851
}  // namespace Botan_Tests
852

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