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

randombit / botan / 11844561993

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

Pull #4435

github

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

91856 of 100744 relevant lines covered (91.18%)

9311006.71 hits per line

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

91.85
/src/tests/test_tls.cpp
1
/*
2
* (C) 2014,2015,2017,2018 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8
#include <fstream>
9
#include <memory>
10

11
#if defined(BOTAN_HAS_TLS)
12
   #include "test_rng.h"
13

14
   #include <botan/tls_alert.h>
15
   #include <botan/tls_policy.h>
16
   #include <botan/tls_session.h>
17
   #include <botan/tls_version.h>
18

19
   #if defined(BOTAN_HAS_TLS_CBC)
20
      #include <botan/internal/tls_cbc.h>
21
   #endif
22

23
#endif
24

25
namespace Botan_Tests {
26

27
#if defined(BOTAN_HAS_TLS)
28

29
class TLS_Session_Tests final : public Test {
×
30
   public:
31
      std::vector<Test::Result> run() override {
1✔
32
         Test::Result result("TLS::Session");
1✔
33
         result.start_timer();
1✔
34

35
         Botan::TLS::Session session(Botan::secure_vector<uint8_t>{0xCC, 0xDD},
1✔
36
                                     Botan::TLS::Protocol_Version::TLS_V12,
37
                                     0xC02F,
38
                                     Botan::TLS::Connection_Side::Client,
39
                                     true,
40
                                     false,
41
                                     std::vector<Botan::X509_Certificate>(),
1✔
42
                                     Botan::TLS::Server_Information("server"),
1✔
43
                                     0x0000,
44
                                     std::chrono::system_clock::now());
2✔
45

46
         const std::string pem = session.PEM_encode();
1✔
47
         Botan::TLS::Session session_from_pem(pem);
1✔
48
         result.test_eq("Roundtrip from pem", session.DER_encode(), session_from_pem.DER_encode());
3✔
49

50
         const auto der = session.DER_encode();
1✔
51
         Botan::TLS::Session session_from_der(der);
1✔
52
         result.test_eq("Roundtrip from der", session.DER_encode(), session_from_der.DER_encode());
3✔
53

54
         const Botan::SymmetricKey key("ABCDEF");
1✔
55
         const std::vector<uint8_t> ctext1 = session.encrypt(key, this->rng());
1✔
56
         const std::vector<uint8_t> ctext2 = session.encrypt(key, this->rng());
1✔
57

58
         result.test_ne(
1✔
59
            "TLS session encryption is non-determinsitic", ctext1.data(), ctext1.size(), ctext2.data(), ctext2.size());
60

61
         const std::vector<uint8_t> expected_hdr = Botan::hex_decode("068B5A9D396C0000F2322CAE");
1✔
62

63
         result.test_eq("tls", "TLS session encryption same header", ctext1.data(), 12, expected_hdr.data(), 12);
1✔
64
         result.test_eq("tls", "TLS session encryption same header", ctext2.data(), 12, expected_hdr.data(), 12);
1✔
65

66
         Botan::TLS::Session dsession = Botan::TLS::Session::decrypt(ctext1.data(), ctext1.size(), key);
1✔
67

68
         Fixed_Output_RNG frng1("00112233445566778899AABBCCDDEEFF802802802802802802802802");
1✔
69
         const std::vector<uint8_t> ctextf1 = session.encrypt(key, frng1);
1✔
70
         Fixed_Output_RNG frng2("00112233445566778899AABBCCDDEEFF802802802802802802802802");
1✔
71
         const std::vector<uint8_t> ctextf2 = session.encrypt(key, frng2);
1✔
72

73
         result.test_eq("Only randomness comes from RNG", ctextf1, ctextf2);
1✔
74

75
         Botan::TLS::Session session2(Botan::secure_vector<uint8_t>{0xCC, 0xEE},
1✔
76
                                      Botan::TLS::Protocol_Version::TLS_V12,
77
                                      0xBAAD,  // cipher suite does not exist
78
                                      Botan::TLS::Connection_Side::Client,
79
                                      true,
80
                                      false,
81
                                      std::vector<Botan::X509_Certificate>(),
1✔
82
                                      Botan::TLS::Server_Information("server"),
1✔
83
                                      0x0000,
84
                                      std::chrono::system_clock::now());
2✔
85
         const std::string pem_with_unknown_ciphersuite = session2.PEM_encode();
1✔
86

87
         result.test_throws("unknown ciphersuite during session parsing",
2✔
88
                            "Serialized TLS session contains unknown cipher suite (47789)",
89
                            [&] { Botan::TLS::Session{pem_with_unknown_ciphersuite}; });
2✔
90

91
         result.end_timer();
1✔
92
         return {result};
3✔
93
      }
9✔
94
};
95

96
BOTAN_REGISTER_TEST("tls", "tls_session", TLS_Session_Tests);
97

98
   #if defined(BOTAN_HAS_TLS_CBC)
99

100
class TLS_CBC_Padding_Tests final : public Text_Based_Test {
×
101
   public:
102
      TLS_CBC_Padding_Tests() : Text_Based_Test("tls_cbc_padding.vec", "Record,Output") {}
2✔
103

104
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
22✔
105
         const std::vector<uint8_t> record = vars.get_req_bin("Record");
22✔
106
         const size_t output = vars.get_req_sz("Output");
22✔
107

108
         uint16_t res = Botan::TLS::check_tls_cbc_padding(record.data(), record.size());
22✔
109

110
         Test::Result result("TLS CBC padding check");
22✔
111
         result.start_timer();
22✔
112
         result.test_eq("Expected", res, output);
22✔
113
         result.end_timer();
22✔
114
         return result;
22✔
115
      }
22✔
116
};
117

118
BOTAN_REGISTER_TEST("tls", "tls_cbc_padding", TLS_CBC_Padding_Tests);
119

120
class TLS_CBC_Tests final : public Text_Based_Test {
×
121
   public:
122
      class ZeroMac : public Botan::MessageAuthenticationCode {
123
         public:
124
            explicit ZeroMac(size_t mac_len) : m_mac_len(mac_len) {}
10✔
125

126
            void clear() override {}
×
127

128
            std::string name() const override { return "ZeroMac"; }
16✔
129

130
            size_t output_length() const override { return m_mac_len; }
20✔
131

132
            void add_data(std::span<const uint8_t> /*input*/) override {}
26✔
133

134
            void final_result(std::span<uint8_t> out) override {
10✔
135
               for(size_t i = 0; i != m_mac_len; ++i) {
206✔
136
                  out[i] = 0;
196✔
137
               }
138
            }
10✔
139

140
            bool has_keying_material() const override { return true; }
×
141

142
            Botan::Key_Length_Specification key_spec() const override {
10✔
143
               return Botan::Key_Length_Specification(0, 0, 1);
10✔
144
            }
145

146
            std::unique_ptr<MessageAuthenticationCode> new_object() const override {
×
147
               return std::make_unique<ZeroMac>(m_mac_len);
×
148
            }
149

150
         private:
151
            void key_schedule(std::span<const uint8_t> /* key */) override {}
10✔
152

153
            size_t m_mac_len;
154
      };
155

156
      class Noop_Block_Cipher : public Botan::BlockCipher {
157
         public:
158
            explicit Noop_Block_Cipher(size_t bs) : m_bs(bs) {}
10✔
159

160
            void encrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override {
×
161
               Botan::copy_mem(out, in, blocks * m_bs);
×
162
            }
×
163

164
            void decrypt_n(const uint8_t in[], uint8_t out[], size_t blocks) const override {
10✔
165
               Botan::copy_mem(out, in, blocks * m_bs);
10✔
166
            }
10✔
167

168
            size_t block_size() const override { return m_bs; }
40✔
169

170
            void clear() override {}
×
171

172
            std::string name() const override { return "noop"; }
10✔
173

174
            bool has_keying_material() const override { return true; }
×
175

176
            Botan::Key_Length_Specification key_spec() const override {
20✔
177
               return Botan::Key_Length_Specification(0, 0, 1);
20✔
178
            }
179

180
            std::unique_ptr<BlockCipher> new_object() const override {
×
181
               return std::make_unique<Noop_Block_Cipher>(m_bs);
×
182
            }
183

184
         private:
185
            void key_schedule(std::span<const uint8_t> /*key*/) override {}
10✔
186

187
            size_t m_bs;
188
      };
189

190
      TLS_CBC_Tests() : Text_Based_Test("tls_cbc.vec", "Blocksize,MACsize,Record,Valid") {}
2✔
191

192
      Test::Result run_one_test(const std::string& /*header*/, const VarMap& vars) override {
10✔
193
         Test::Result result("TLS CBC");
10✔
194
         result.start_timer();
10✔
195

196
         const size_t block_size = vars.get_req_sz("Blocksize");
10✔
197
         const size_t mac_len = vars.get_req_sz("MACsize");
10✔
198
         const std::vector<uint8_t> record = vars.get_req_bin("Record");
10✔
199
         const bool is_valid = vars.get_req_sz("Valid") == 1;
10✔
200

201
         // todo test permutations
202
         bool encrypt_then_mac = false;
10✔
203

204
         Botan::TLS::TLS_CBC_HMAC_AEAD_Decryption tls_cbc(std::make_unique<Noop_Block_Cipher>(block_size),
20✔
205
                                                          std::make_unique<ZeroMac>(mac_len),
10✔
206
                                                          0,
207
                                                          0,
208
                                                          Botan::TLS::Protocol_Version::TLS_V12,
209
                                                          encrypt_then_mac);
20✔
210

211
         tls_cbc.set_key(std::vector<uint8_t>(0));
10✔
212
         std::vector<uint8_t> ad(13);
10✔
213
         tls_cbc.set_associated_data(ad.data(), ad.size());
10✔
214

215
         Botan::secure_vector<uint8_t> vec(record.begin(), record.end());
10✔
216

217
         try {
10✔
218
            tls_cbc.finish(vec, 0);
10✔
219
            if(is_valid) {
4✔
220
               result.test_success("Accepted valid TLS-CBC ciphertext");
8✔
221
            } else {
222
               result.test_failure("Accepted invalid TLS-CBC ciphertext");
×
223
            }
224
         } catch(std::exception&) {
6✔
225
            if(is_valid) {
6✔
226
               result.test_failure("Rejected valid TLS-CBC ciphertext");
×
227
            } else {
228
               result.test_success("Accepted invalid TLS-CBC ciphertext");
12✔
229
            }
230
         }
6✔
231

232
         result.end_timer();
10✔
233
         return result;
10✔
234
      }
30✔
235
};
236

237
BOTAN_REGISTER_TEST("tls", "tls_cbc", TLS_CBC_Tests);
238

239
   #endif
240

241
class Test_TLS_Alert_Strings : public Test {
1✔
242
   public:
243
      std::vector<Test::Result> run() override {
1✔
244
         Test::Result result("TLS::Alert::type_string");
1✔
245
         result.start_timer();
1✔
246

247
         const std::vector<Botan::TLS::Alert::Type> alert_types = {
1✔
248
            Botan::TLS::Alert::CloseNotify,
249
            Botan::TLS::Alert::UnexpectedMessage,
250
            Botan::TLS::Alert::BadRecordMac,
251
            Botan::TLS::Alert::DecryptionFailed,
252
            Botan::TLS::Alert::RecordOverflow,
253
            Botan::TLS::Alert::DecompressionFailure,
254
            Botan::TLS::Alert::HandshakeFailure,
255
            Botan::TLS::Alert::NoCertificate,
256
            Botan::TLS::Alert::BadCertificate,
257
            Botan::TLS::Alert::UnsupportedCertificate,
258
            Botan::TLS::Alert::CertificateRevoked,
259
            Botan::TLS::Alert::CertificateExpired,
260
            Botan::TLS::Alert::CertificateUnknown,
261
            Botan::TLS::Alert::IllegalParameter,
262
            Botan::TLS::Alert::UnknownCA,
263
            Botan::TLS::Alert::AccessDenied,
264
            Botan::TLS::Alert::DecodeError,
265
            Botan::TLS::Alert::DecryptError,
266
            Botan::TLS::Alert::ExportRestriction,
267
            Botan::TLS::Alert::ProtocolVersion,
268
            Botan::TLS::Alert::InsufficientSecurity,
269
            Botan::TLS::Alert::InternalError,
270
            Botan::TLS::Alert::InappropriateFallback,
271
            Botan::TLS::Alert::UserCanceled,
272
            Botan::TLS::Alert::NoRenegotiation,
273
            Botan::TLS::Alert::MissingExtension,
274
            Botan::TLS::Alert::UnsupportedExtension,
275
            Botan::TLS::Alert::CertificateUnobtainable,
276
            Botan::TLS::Alert::UnrecognizedName,
277
            Botan::TLS::Alert::BadCertificateStatusResponse,
278
            Botan::TLS::Alert::BadCertificateHashValue,
279
            Botan::TLS::Alert::UnknownPSKIdentity,
280
            Botan::TLS::Alert::NoApplicationProtocol,
281
         };
1✔
282

283
         std::set<std::string> seen;
1✔
284

285
         for(auto alert : alert_types) {
34✔
286
            const std::string str = Botan::TLS::Alert(alert).type_string();
33✔
287
            result.test_eq("No duplicate strings", seen.count(str), 0);
33✔
288
            seen.insert(str);
33✔
289
         }
33✔
290

291
         Botan::TLS::Alert unknown_alert = Botan::TLS::Alert({01, 66});
1✔
292

293
         result.test_eq("Unknown alert str", unknown_alert.type_string(), "unrecognized_alert_66");
2✔
294

295
         result.end_timer();
1✔
296
         return {result};
3✔
297
      }
2✔
298
};
299

300
BOTAN_REGISTER_TEST("tls", "tls_alert_strings", Test_TLS_Alert_Strings);
301

302
class Test_TLS_Policy_Text : public Test {
1✔
303
   public:
304
      std::vector<Test::Result> run() override {
1✔
305
         Test::Result result("TLS Policy");
1✔
306
         result.start_timer();
1✔
307

308
         const std::vector<std::string> policies = {"default", "suiteb_128", "suiteb_192", "strict", "datagram", "bsi"};
1✔
309

310
         for(const std::string& policy : policies) {
7✔
311
            const std::string from_policy_obj = tls_policy_string(policy);
6✔
312
            std::string from_file =
6✔
313
   #if defined(BOTAN_HAS_TLS_13)
314
               read_tls_policy(policy + (policy == "default" || policy == "strict" ? "_tls13" : ""));
8✔
315
   #else
316
               read_tls_policy(policy);
317
   #endif
318

319
            result.test_eq("Values for TLS " + policy + " policy", from_file, from_policy_obj);
18✔
320
         }
6✔
321

322
         result.end_timer();
1✔
323
         return {result};
3✔
324
      }
2✔
325

326
   private:
327
      static std::string read_tls_policy(const std::string& policy_str) {
6✔
328
         const std::string fspath = Test::data_file("tls-policy/" + policy_str + ".txt");
18✔
329

330
         std::ifstream is(fspath.c_str());
6✔
331
         if(!is.good()) {
6✔
332
            throw Test_Error("Missing policy file " + fspath);
×
333
         }
334

335
         Botan::TLS::Text_Policy policy(is);
6✔
336
         return policy.to_string();
6✔
337
      }
6✔
338

339
      static std::string tls_policy_string(const std::string& policy_str) {
6✔
340
         std::unique_ptr<Botan::TLS::Policy> policy;
6✔
341
         if(policy_str == "default") {
6✔
342
            policy = std::make_unique<Botan::TLS::Policy>();
1✔
343
         } else if(policy_str == "suiteb_128") {
5✔
344
            policy = std::make_unique<Botan::TLS::NSA_Suite_B_128>();
1✔
345
         } else if(policy_str == "suiteb_192") {
4✔
346
            policy = std::make_unique<Botan::TLS::NSA_Suite_B_192>();
1✔
347
         } else if(policy_str == "bsi") {
3✔
348
            policy = std::make_unique<Botan::TLS::BSI_TR_02102_2>();
1✔
349
         } else if(policy_str == "strict") {
2✔
350
            policy = std::make_unique<Botan::TLS::Strict_Policy>();
1✔
351
         } else if(policy_str == "datagram") {
1✔
352
            policy = std::make_unique<Botan::TLS::Datagram_Policy>();
1✔
353
         } else {
354
            throw Test_Error("Unknown TLS policy type '" + policy_str + "'");
×
355
         }
356

357
         return policy->to_string();
6✔
358
      }
6✔
359
};
360

361
BOTAN_REGISTER_TEST("tls", "tls_policy_text", Test_TLS_Policy_Text);
362

363
class Test_TLS_Ciphersuites : public Test {
1✔
364
   public:
365
      std::vector<Test::Result> run() override {
1✔
366
         Test::Result result("TLS::Ciphersuite");
1✔
367
         result.start_timer();
1✔
368

369
         for(size_t csuite_id = 0; csuite_id <= 0xFFFF; ++csuite_id) {
65,537✔
370
            const uint16_t csuite_id16 = static_cast<uint16_t>(csuite_id);
65,536✔
371
            auto ciphersuite = Botan::TLS::Ciphersuite::by_id(csuite_id16);
65,536✔
372

373
            if(ciphersuite && ciphersuite->valid()) {
65,536✔
374
               result.test_eq("Valid Ciphersuite is not SCSV", Botan::TLS::Ciphersuite::is_scsv(csuite_id16), false);
94✔
375

376
               if(ciphersuite->cbc_ciphersuite() == false) {
94✔
377
                  result.test_eq("Expected AEAD ciphersuite", ciphersuite->aead_ciphersuite(), true);
64✔
378
                  result.test_eq("Expected MAC name for AEAD ciphersuites", ciphersuite->mac_algo(), "AEAD");
128✔
379
               } else {
380
                  result.test_eq("Did not expect AEAD ciphersuite", ciphersuite->aead_ciphersuite(), false);
30✔
381
                  result.test_eq(
90✔
382
                     "MAC algo and PRF algo same for CBC suites", ciphersuite->prf_algo(), ciphersuite->mac_algo());
60✔
383
               }
384

385
               // TODO more tests here
386
            }
387
         }
388

389
         result.end_timer();
1✔
390
         return {result};
3✔
391
      }
2✔
392
};
393

394
BOTAN_REGISTER_TEST("tls", "tls_ciphersuites", Test_TLS_Ciphersuites);
395

396
class Test_TLS_Algo_Strings : public Test {
1✔
397
   public:
398
      std::vector<Test::Result> run() override {
1✔
399
         std::vector<Test::Result> results;
1✔
400

401
         results.push_back(test_auth_method_strings());
2✔
402
         results.push_back(test_kex_algo_strings());
2✔
403
         results.push_back(test_tls_sig_method_strings());
2✔
404

405
         return results;
1✔
406
      }
×
407

408
   private:
409
      static Test::Result test_tls_sig_method_strings() {
1✔
410
         Test::Result result("TLS::Signature_Scheme");
1✔
411
         result.start_timer();
1✔
412

413
         std::vector<Botan::TLS::Signature_Scheme> schemes = Botan::TLS::Signature_Scheme::all_available_schemes();
1✔
414

415
         std::set<std::string> scheme_strs;
1✔
416
         for(auto scheme : schemes) {
10✔
417
            std::string scheme_str = scheme.to_string();
9✔
418

419
            result.test_eq("Scheme strings unique", scheme_strs.count(scheme_str), 0);
9✔
420

421
            scheme_strs.insert(scheme_str);
9✔
422
         }
9✔
423

424
         result.end_timer();
1✔
425
         return result;
2✔
426
      }
1✔
427

428
      static Test::Result test_auth_method_strings() {
1✔
429
         Test::Result result("TLS::Auth_Method");
1✔
430
         result.start_timer();
1✔
431

432
         const std::vector<Botan::TLS::Auth_Method> auth_methods({
1✔
433
            Botan::TLS::Auth_Method::RSA,
434
            Botan::TLS::Auth_Method::ECDSA,
435
            Botan::TLS::Auth_Method::IMPLICIT,
436
         });
1✔
437

438
         for(Botan::TLS::Auth_Method meth : auth_methods) {
4✔
439
            std::string meth_str = Botan::TLS::auth_method_to_string(meth);
3✔
440
            result.test_ne("Method string is not empty", meth_str, "");
6✔
441
            Botan::TLS::Auth_Method meth2 = Botan::TLS::auth_method_from_string(meth_str);
3✔
442
            result.confirm("Decoded method matches", meth == meth2);
6✔
443
         }
3✔
444

445
         result.end_timer();
1✔
446
         return result;
1✔
447
      }
1✔
448

449
      static Test::Result test_kex_algo_strings() {
1✔
450
         Test::Result result("TLS::Kex_Algo");
1✔
451
         result.start_timer();
1✔
452

453
         const std::vector<Botan::TLS::Kex_Algo> kex_algos({Botan::TLS::Kex_Algo::STATIC_RSA,
1✔
454
                                                            Botan::TLS::Kex_Algo::DH,
455
                                                            Botan::TLS::Kex_Algo::ECDH,
456
                                                            Botan::TLS::Kex_Algo::PSK,
457
                                                            Botan::TLS::Kex_Algo::ECDHE_PSK});
1✔
458

459
         for(Botan::TLS::Kex_Algo meth : kex_algos) {
6✔
460
            std::string meth_str = Botan::TLS::kex_method_to_string(meth);
5✔
461
            result.test_ne("Method string is not empty", meth_str, "");
10✔
462
            Botan::TLS::Kex_Algo meth2 = Botan::TLS::kex_method_from_string(meth_str);
5✔
463
            result.confirm("Decoded method matches", meth == meth2);
10✔
464
         }
5✔
465

466
         result.end_timer();
1✔
467
         return result;
1✔
468
      }
1✔
469
};
470

471
BOTAN_REGISTER_TEST("tls", "tls_algo_strings", Test_TLS_Algo_Strings);
472

473
#endif
474

475
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc