/src/nss/fuzz/targets/tls_server.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #include <cassert> |
6 | | #include <cstdint> |
7 | | #include <iostream> |
8 | | |
9 | | #include "blapi.h" |
10 | | #include "seccomon.h" |
11 | | #include "ssl.h" |
12 | | #include "sslimpl.h" |
13 | | |
14 | | #include "base/database.h" |
15 | | #include "base/mutate.h" |
16 | | #include "tls/common.h" |
17 | | #include "tls/mutators.h" |
18 | | #include "tls/server_certs.h" |
19 | | #include "tls/server_config.h" |
20 | | #include "tls/socket.h" |
21 | | |
22 | | #ifdef IS_DTLS_FUZZ |
23 | | #define ImportFD DTLS_ImportFD |
24 | | #else |
25 | 66.9k | #define ImportFD SSL_ImportFD |
26 | | #endif // IS_DTLS_FUZZ |
27 | | |
28 | | class SSLServerSessionCache { |
29 | | public: |
30 | 4 | SSLServerSessionCache() { |
31 | 4 | assert(SSL_ConfigServerSessionIDCache(1024, 0, 0, ".") == SECSuccess); |
32 | 4 | } |
33 | | |
34 | 4 | ~SSLServerSessionCache() { |
35 | 4 | assert(SSL_ShutdownServerSessionIDCache() == SECSuccess); |
36 | 4 | } |
37 | | }; |
38 | | |
39 | 4 | static PRStatus InitModelSocket(void* arg) { |
40 | 4 | PRFileDesc* fd = reinterpret_cast<PRFileDesc*>(arg); |
41 | | |
42 | 4 | TlsCommon::EnableAllCipherSuites(fd); |
43 | 4 | TlsServer::InstallServerCertificates(fd); |
44 | | |
45 | 4 | return PR_SUCCESS; |
46 | 4 | } |
47 | | |
48 | 33.4k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
49 | 33.4k | static NSSDatabase db = NSSDatabase(); |
50 | 33.4k | static SSLServerSessionCache cache = SSLServerSessionCache(); |
51 | 33.4k | static PRDescIdentity id = PR_GetUniqueIdentity("fuzz-server"); |
52 | | |
53 | | // Create model socket. |
54 | 33.4k | static ScopedPRFileDesc model(ImportFD(nullptr, PR_NewTCPSocket())); |
55 | 33.4k | assert(model); |
56 | | |
57 | | // Initialize the model socket once. |
58 | 33.4k | static PRCallOnceType initModelOnce; |
59 | 33.4k | PR_CallOnceWithArg(&initModelOnce, InitModelSocket, model.get()); |
60 | | |
61 | | // Create and import dummy socket. |
62 | 33.4k | TlsSocket::DummyPrSocket socket = TlsSocket::DummyPrSocket(data, size); |
63 | 33.4k | ScopedPRFileDesc prFd(DummyIOLayerMethods::CreateFD(id, &socket)); |
64 | 33.4k | PRFileDesc* sslFd = ImportFD(model.get(), prFd.get()); |
65 | 33.4k | assert(sslFd == prFd.get()); |
66 | | |
67 | | // Derive server config from input data. |
68 | 33.4k | TlsServer::Config config = TlsServer::Config(data, size); |
69 | | |
70 | 33.4k | if (ssl_trace >= 90) { |
71 | 0 | std::cerr << config << "\n"; |
72 | 0 | } |
73 | | |
74 | | // Keeping things determinstic. |
75 | 33.4k | assert(RNG_RandomUpdate(NULL, 0) == SECSuccess); |
76 | 33.4k | assert(SSL_SetURL(sslFd, "fuzz.server") == SECSuccess); |
77 | | |
78 | 33.4k | TlsCommon::EnableAllProtocolVersions(); |
79 | 33.4k | TlsCommon::EnableAllCipherSuites(sslFd); |
80 | 33.4k | TlsCommon::FixTime(sslFd); |
81 | | |
82 | | // Set socket options from server config. |
83 | 33.4k | config.SetCallbacks(sslFd); |
84 | 33.4k | config.SetSocketOptions(sslFd); |
85 | | |
86 | | // Perform the acutal handshake. |
87 | 33.4k | TlsCommon::DoHandshake(sslFd, true); |
88 | | |
89 | | // Clear the cache. We never want to resume as we couldn't reproduce that. |
90 | 33.4k | SSL_ClearSessionCache(); |
91 | | |
92 | 33.4k | return 0; |
93 | 33.4k | } |
94 | | |
95 | | extern "C" size_t LLVMFuzzerCustomMutator(uint8_t* data, size_t size, |
96 | 0 | size_t maxSize, unsigned int seed) { |
97 | 0 | return CustomMutate( |
98 | 0 | {TlsMutators::DropRecord, TlsMutators::ShuffleRecords, |
99 | 0 | TlsMutators::DuplicateRecord, TlsMutators::TruncateRecord, |
100 | 0 | TlsMutators::FragmentRecord}, |
101 | 0 | data, size, maxSize, seed); |
102 | 0 | } |
103 | | |
104 | | extern "C" size_t LLVMFuzzerCustomCrossOver(const uint8_t* data1, size_t size1, |
105 | | const uint8_t* data2, size_t size2, |
106 | | uint8_t* out, size_t maxOutSize, |
107 | 0 | unsigned int seed) { |
108 | 0 | return TlsMutators::CrossOver(data1, size1, data2, size2, out, maxOutSize, |
109 | 0 | seed); |
110 | 0 | } |