1 /*
2 * Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.openssl.org/source/license.html
8 * or in the file LICENSE in the source distribution.
9 */
10
11 #include <openssl/ssl.h>
12 #include <openssl/err.h>
13 #include <openssl/bio.h>
14 #include "fuzzer.h"
15 #include "internal/sockets.h"
16 #include "internal/time.h"
17 #include "internal/quic_ssl.h"
18
19 /* unused, to avoid warning. */
20 static int idx;
21
22 static OSSL_TIME fake_now;
23
fake_now_cb(void * arg)24 static OSSL_TIME fake_now_cb(void *arg)
25 {
26 return fake_now;
27 }
28
FuzzerInitialize(int * argc,char *** argv)29 int FuzzerInitialize(int *argc, char ***argv)
30 {
31 STACK_OF(SSL_COMP) *comp_methods;
32
33 FuzzerSetRand();
34 OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);
35 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
36 ERR_clear_error();
37 CRYPTO_free_ex_index(0, -1);
38 idx = SSL_get_ex_data_X509_STORE_CTX_idx();
39 comp_methods = SSL_COMP_get_compression_methods();
40 if (comp_methods != NULL)
41 sk_SSL_COMP_sort(comp_methods);
42
43 return 1;
44 }
45
46 #define HANDSHAKING 0
47 #define READING 1
48 #define WRITING 2
49 #define ACCEPTING_STREAM 3
50 #define CREATING_STREAM 4
51 #define SWAPPING_STREAM 5
52
53 /*
54 * This callback validates and negotiates the desired ALPN on the server side.
55 * Accept any ALPN.
56 */
select_alpn(SSL * ssl,const unsigned char ** out,unsigned char * out_len,const unsigned char * in,unsigned int in_len,void * arg)57 static int select_alpn(SSL *ssl, const unsigned char **out,
58 unsigned char *out_len, const unsigned char *in,
59 unsigned int in_len, void *arg)
60 {
61 return SSL_TLSEXT_ERR_OK;
62 }
63
FuzzerTestOneInput(const uint8_t * buf,size_t len)64 int FuzzerTestOneInput(const uint8_t *buf, size_t len)
65 {
66 SSL *server = NULL, *stream = NULL;
67 SSL *allstreams[] = {NULL, NULL, NULL, NULL};
68 size_t i, thisstream = 0, numstreams = 1;
69 BIO *in;
70 BIO *out;
71 SSL_CTX *ctx;
72 struct timeval tv;
73 int state = HANDSHAKING;
74 uint8_t tmp[1024];
75 int writelen = 0;
76
77 if (len == 0)
78 return 0;
79
80 ctx = SSL_CTX_new(OSSL_QUIC_server_method());
81 if (ctx == NULL)
82 goto end;
83
84 SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
85
86 server = SSL_new_listener(ctx, 0);
87 allstreams[0] = stream = server;
88 if (server == NULL)
89 goto end;
90
91 fake_now = ossl_ms2time(1);
92 if (!ossl_quic_set_override_now_cb(server, fake_now_cb, NULL))
93 goto end;
94
95 in = BIO_new(BIO_s_dgram_mem());
96 if (in == NULL)
97 goto end;
98 out = BIO_new(BIO_s_dgram_mem());
99 if (out == NULL) {
100 BIO_free(in);
101 goto end;
102 }
103 if (!BIO_dgram_set_caps(out, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) {
104 BIO_free(in);
105 BIO_free(out);
106 goto end;
107 }
108 SSL_set_bio(server, in, out);
109 SSL_set_accept_state(server);
110
111 for (;;) {
112 size_t size;
113 uint64_t nxtpktms = 0;
114 OSSL_TIME nxtpkt = ossl_time_zero(), nxttimeout;
115 int isinf, ret = 0;
116
117 if (len >= 2) {
118 if (len >= 5 && buf[0] == 0xff && buf[1] == 0xff) {
119 switch (buf[2]) {
120 case 0x00:
121 if (state == READING)
122 state = ACCEPTING_STREAM;
123 break;
124 case 0x01:
125 if (state == READING)
126 state = CREATING_STREAM;
127 break;
128 case 0x02:
129 if (state == READING)
130 state = SWAPPING_STREAM;
131 break;
132 default:
133 /* ignore */
134 break;
135 }
136 len -= 3;
137 buf += 3;
138 }
139 nxtpktms = buf[0] + (buf[1] << 8);
140 nxtpkt = ossl_time_add(fake_now, ossl_ms2time(nxtpktms));
141 len -= 2;
142 buf += 2;
143 }
144
145 for (;;) {
146 switch (state) {
147 case HANDSHAKING:
148 ret = SSL_accept_connection(stream, 0) != NULL;
149 if (ret == 1)
150 state = READING;
151 break;
152
153 case READING:
154 ret = SSL_read(stream, tmp, sizeof(tmp));
155 if (ret > 0) {
156 state = WRITING;
157 writelen = ret;
158 assert(writelen <= (int)sizeof(tmp));
159 }
160 break;
161
162 case WRITING:
163 ret = SSL_write(stream, tmp, writelen);
164 if (ret > 0)
165 state = READING;
166 break;
167
168 case ACCEPTING_STREAM:
169 state = READING;
170 ret = 1;
171 if (numstreams == OSSL_NELEM(allstreams)
172 || SSL_get_accept_stream_queue_len(server) == 0)
173 break;
174 thisstream = numstreams;
175 stream = allstreams[numstreams++] = SSL_accept_stream(server, 0);
176 if (stream == NULL)
177 goto end;
178 break;
179
180 case CREATING_STREAM:
181 state = READING;
182 ret = 1;
183 if (numstreams == OSSL_NELEM(allstreams))
184 break;
185 stream = SSL_new_stream(server, 0);
186 if (stream == NULL) {
187 /* Ignore, and go back to the previous stream */
188 stream = allstreams[thisstream];
189 break;
190 }
191 thisstream = numstreams;
192 allstreams[numstreams++] = stream;
193 break;
194
195 case SWAPPING_STREAM:
196 state = READING;
197 ret = 1;
198 if (numstreams == 1)
199 break;
200 if (++thisstream == numstreams)
201 thisstream = 0;
202 stream = allstreams[thisstream];
203 break;
204 }
205 assert(stream != NULL);
206 assert(thisstream < numstreams);
207 if (ret <= 0) {
208 switch (SSL_get_error(stream, ret)) {
209 case SSL_ERROR_WANT_READ:
210 case SSL_ERROR_WANT_WRITE:
211 break;
212 default:
213 goto end;
214 }
215 }
216
217 if (!SSL_get_event_timeout(server, &tv, &isinf))
218 goto end;
219
220 if (isinf) {
221 fake_now = nxtpkt;
222 break;
223 } else {
224 nxttimeout = ossl_time_add(fake_now,
225 ossl_time_from_timeval(tv));
226 if (len > 3 && ossl_time_compare(nxttimeout, nxtpkt) >= 0) {
227 fake_now = nxtpkt;
228 break;
229 }
230 fake_now = nxttimeout;
231 }
232 }
233
234 if (len <= 3)
235 break;
236
237 size = buf[0] + (buf[1] << 8);
238 if (size > len - 2)
239 break;
240
241 if (size > 0)
242 BIO_write(in, buf + 2, size);
243 len -= size + 2;
244 buf += size + 2;
245 }
246 end:
247 for (i = 0; i < numstreams; i++)
248 SSL_free(allstreams[i]);
249 ERR_clear_error();
250 SSL_CTX_free(ctx);
251
252 return 0;
253 }
254
FuzzerCleanup(void)255 void FuzzerCleanup(void)
256 {
257 FuzzerClearRand();
258 }
259