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 24 static OSSL_TIME fake_now_cb(void *arg) 25 { 26 return fake_now; 27 } 28 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 */ 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 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 255 void FuzzerCleanup(void) 256 { 257 FuzzerClearRand(); 258 } 259