Coverage Report

Created: 2025-04-11 06:34

/src/botan/src/fuzzer/tls_server.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* (C) 2015,2016 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6
7
#include "fuzzers.h"
8
9
#include <botan/data_src.h>
10
#include <botan/hex.h>
11
#include <botan/pkcs8.h>
12
#include <botan/tls_server.h>
13
#include <botan/tls_session_manager_noop.h>
14
15
#include <memory>
16
17
namespace {
18
19
const char* const fixed_ecdsa_key =
20
   "-----BEGIN PRIVATE KEY-----"
21
   "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgfUjnfxgvrIyrqa5N"
22
   "47X1W50cVStDPbASwRcY6zqehjyhRANCAAQTNF0poMBM4tuCY50NrDJU8za/SK45"
23
   "erOdFpGK7KRWtBE9zNj6J0f1UB+K8GdekFD2me+iL63v+uBqo/PHRPT9"
24
   "-----END PRIVATE KEY-----";
25
26
const char* const fixed_ecdsa_cert =
27
   "-----BEGIN CERTIFICATE-----"
28
   "MIIB3zCCAYWgAwIBAgIRAPFi6dun9OY7YLuZHqKzdEMwCgYIKoZIzj0EAwIwOTEa"
29
   "MBgGA1UEAwwRSXQncyBGdXp6aW5nIFRpbWUxCzAJBgNVBAYTAlZUMQ4wDAYDVQQK"
30
   "EwVCb3RhbjAeFw0yNTAxMjAxMzI0MjdaFw0zODAxMTgxMzI0MjdaMDkxGjAYBgNV"
31
   "BAMMEUl0J3MgRnV6emluZyBUaW1lMQswCQYDVQQGEwJWVDEOMAwGA1UEChMFQm90"
32
   "YW4wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQTNF0poMBM4tuCY50NrDJU8za/"
33
   "SK45erOdFpGK7KRWtBE9zNj6J0f1UB+K8GdekFD2me+iL63v+uBqo/PHRPT9o24w"
34
   "bDAhBgNVHQ4EGgQYevp/SCkZVWPKNAUSez17HTOyneXEWwpEMBQGA1UdEQQNMAuC"
35
   "CWxvY2FsaG9zdDAMBgNVHRMBAf8EAjAAMCMGA1UdIwQcMBqAGHr6f0gpGVVjyjQF"
36
   "Ens9ex0zsp3lxFsKRDAKBggqhkjOPQQDAgNIADBFAiEApqVCYhySxK/8GLq8wlPh"
37
   "MeBg8CwKO83s1h/GYQZD4CUCID5Mzh5mwrkkAuSENjLXAD4dtiu91Zsoye5J0uuU"
38
   "60v7"
39
   "-----END CERTIFICATE-----";
40
41
class Fuzzer_TLS_Server_Creds : public Botan::Credentials_Manager {
42
   public:
43
6.93k
      Fuzzer_TLS_Server_Creds() {
44
6.93k
         Botan::DataSource_Memory cert_in(fixed_ecdsa_cert);
45
6.93k
         m_ecdsa_cert = std::make_unique<Botan::X509_Certificate>(cert_in);
46
47
6.93k
         Botan::DataSource_Memory key_in(fixed_ecdsa_key);
48
6.93k
         m_ecdsa_key.reset(Botan::PKCS8::load_key(key_in).release());
49
6.93k
      }
50
51
      std::vector<Botan::X509_Certificate> cert_chain(
52
         const std::vector<std::string>& algos,
53
         const std::vector<Botan::AlgorithmIdentifier>& /*signature_schemes*/,
54
         const std::string& /*type*/,
55
64.2k
         const std::string& /*hostname*/) override {
56
64.2k
         std::vector<Botan::X509_Certificate> v;
57
58
64.2k
         for(const auto& algo : algos) {
59
64.2k
            if(algo == "ECDSA") {
60
21.4k
               v.push_back(*m_ecdsa_cert);
61
21.4k
               break;
62
21.4k
            }
63
64.2k
         }
64
65
64.2k
         return v;
66
64.2k
      }
67
68
      std::shared_ptr<Botan::Private_Key> private_key_for(const Botan::X509_Certificate& /*cert*/,
69
                                                          const std::string& type,
70
9
                                                          const std::string& /*context*/) override {
71
9
         if(type == "ECDSA") {
72
0
            return m_ecdsa_key;
73
0
         }
74
9
         return nullptr;
75
9
      }
76
77
1.08k
      Botan::secure_vector<uint8_t> session_ticket_key() override {
78
1.08k
         return Botan::hex_decode_locked("AABBCCDDEEFF00112233445566778899");
79
1.08k
      }
80
81
5.23k
      Botan::secure_vector<uint8_t> dtls_cookie_secret() override {
82
5.23k
         return Botan::hex_decode_locked("AABBCCDDEEFF00112233445566778899");
83
5.23k
      }
84
85
21.1k
      std::string psk_identity_hint(const std::string&, const std::string&) override { return "psk_hint"; }
86
87
0
      std::string psk_identity(const std::string&, const std::string&, const std::string&) override { return "psk_id"; }
88
89
      std::vector<Botan::TLS::ExternalPSK> find_preshared_keys(
90
         std::string_view host,
91
         Botan::TLS::Connection_Side whoami,
92
         const std::vector<std::string>& identities = {},
93
5.40k
         const std::optional<std::string>& prf = std::nullopt) override {
94
5.40k
         if(!identities.empty() && std::find(identities.begin(), identities.end(), "psk_id") == identities.end()) {
95
76
            return Botan::Credentials_Manager::find_preshared_keys(host, whoami, identities, prf);
96
76
         }
97
98
5.32k
         std::vector<Botan::TLS::ExternalPSK> psks;
99
5.32k
         psks.emplace_back("psk_id", "SHA-256", Botan::hex_decode_locked("AABBCCDDEEFF00112233445566778899"));
100
5.32k
         return psks;
101
5.40k
      }
102
103
   private:
104
      std::unique_ptr<Botan::X509_Certificate> m_ecdsa_cert;
105
      std::shared_ptr<Botan::Private_Key> m_ecdsa_key;
106
};
107
108
class Fuzzer_TLS_Policy : public Botan::TLS::Policy {
109
   public:
110
21.4k
      std::vector<uint16_t> ciphersuite_list(Botan::TLS::Protocol_Version) const override {
111
21.4k
         std::vector<uint16_t> ciphersuites;
112
113
2.01M
         for(auto&& suite : Botan::TLS::Ciphersuite::all_known_ciphersuites()) {
114
2.01M
            if(suite.valid()) {
115
2.01M
               ciphersuites.push_back(suite.ciphersuite_code());
116
2.01M
            }
117
2.01M
         }
118
119
21.4k
         return ciphersuites;
120
21.4k
      }
121
};
122
123
class Fuzzer_TLS_Server_Callbacks : public Botan::TLS::Callbacks {
124
   public:
125
73.7k
      void tls_emit_data(std::span<const uint8_t>) override {
126
         // discard
127
73.7k
      }
128
129
0
      void tls_record_received(uint64_t, std::span<const uint8_t>) override {
130
         // ignore peer data
131
0
      }
132
133
22.1k
      void tls_alert(Botan::TLS::Alert) override {
134
         // ignore alert
135
22.1k
      }
136
137
4.41k
      std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos) override {
138
4.41k
         if(client_protos.size() > 1) {
139
429
            return client_protos[0];
140
3.98k
         } else {
141
3.98k
            return "fuzzy";
142
3.98k
         }
143
4.41k
      }
144
145
      void tls_verify_cert_chain(const std::vector<Botan::X509_Certificate>& cert_chain,
146
                                 const std::vector<std::optional<Botan::OCSP::Response>>& ocsp_responses,
147
                                 const std::vector<Botan::Certificate_Store*>& trusted_roots,
148
                                 Botan::Usage_Type usage,
149
                                 std::string_view hostname,
150
0
                                 const Botan::TLS::Policy& policy) override {
151
0
         try {
152
            // try to validate to exercise those code paths
153
0
            Botan::TLS::Callbacks::tls_verify_cert_chain(
154
0
               cert_chain, ocsp_responses, trusted_roots, usage, hostname, policy);
155
0
         } catch(...) {
156
            // ignore validation result
157
0
         }
158
0
      }
159
};
160
161
}  // namespace
162
163
6.93k
void fuzz(std::span<const uint8_t> in) {
164
6.93k
   if(in.size() <= 1) {
165
1
      return;
166
1
   }
167
168
6.93k
   auto session_manager = std::make_shared<Botan::TLS::Session_Manager_Noop>();
169
6.93k
   auto policy = std::make_shared<Fuzzer_TLS_Policy>();
170
6.93k
   Botan::TLS::Server_Information info("server.name", 443);
171
6.93k
   auto creds = std::make_shared<Fuzzer_TLS_Server_Creds>();
172
6.93k
   auto callbacks = std::make_shared<Fuzzer_TLS_Server_Callbacks>();
173
174
6.93k
   const bool is_datagram = in[0] & 1;
175
176
6.93k
   Botan::TLS::Server server(callbacks, session_manager, creds, policy, fuzzer_rng_as_shared(), is_datagram);
177
178
6.93k
   try {
179
6.93k
      server.received_data(in.subspan(1, in.size() - 1));
180
6.93k
   } catch(std::exception& e) {}
181
6.93k
}