/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 | } |