Path: blob/main/crypto/openssl/fuzz/quic-server.c
104265 views
/*1* Copyright 2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License");4* you may not use this file except in compliance with the License.5* You may obtain a copy of the License at6* https://www.openssl.org/source/license.html7* or in the file LICENSE in the source distribution.8*/910#include <openssl/ssl.h>11#include <openssl/err.h>12#include <openssl/bio.h>13#include "fuzzer.h"14#include "internal/sockets.h"15#include "internal/time.h"16#include "internal/quic_ssl.h"1718/* unused, to avoid warning. */19static int idx;2021static OSSL_TIME fake_now;2223static OSSL_TIME fake_now_cb(void *arg)24{25return fake_now;26}2728int FuzzerInitialize(int *argc, char ***argv)29{30STACK_OF(SSL_COMP) *comp_methods;3132FuzzerSetRand();33OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);34OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);35ERR_clear_error();36CRYPTO_free_ex_index(0, -1);37idx = SSL_get_ex_data_X509_STORE_CTX_idx();38comp_methods = SSL_COMP_get_compression_methods();39if (comp_methods != NULL)40sk_SSL_COMP_sort(comp_methods);4142return 1;43}4445#define HANDSHAKING 046#define READING 147#define WRITING 248#define ACCEPTING_STREAM 349#define CREATING_STREAM 450#define SWAPPING_STREAM 55152/*53* This callback validates and negotiates the desired ALPN on the server side.54* Accept any ALPN.55*/56static int select_alpn(SSL *ssl, const unsigned char **out,57unsigned char *out_len, const unsigned char *in,58unsigned int in_len, void *arg)59{60return SSL_TLSEXT_ERR_OK;61}6263int FuzzerTestOneInput(const uint8_t *buf, size_t len)64{65SSL *server = NULL, *stream = NULL;66SSL *allstreams[] = { NULL, NULL, NULL, NULL };67size_t i, thisstream = 0, numstreams = 1;68BIO *in;69BIO *out;70SSL_CTX *ctx;71struct timeval tv;72int state = HANDSHAKING;73uint8_t tmp[1024];74int writelen = 0;7576if (len == 0)77return 0;7879ctx = SSL_CTX_new(OSSL_QUIC_server_method());80if (ctx == NULL)81goto end;8283SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);8485server = SSL_new_listener(ctx, 0);86allstreams[0] = stream = server;87if (server == NULL)88goto end;8990fake_now = ossl_ms2time(1);91if (!ossl_quic_set_override_now_cb(server, fake_now_cb, NULL))92goto end;9394in = BIO_new(BIO_s_dgram_mem());95if (in == NULL)96goto end;97out = BIO_new(BIO_s_dgram_mem());98if (out == NULL) {99BIO_free(in);100goto end;101}102if (!BIO_dgram_set_caps(out, BIO_DGRAM_CAP_HANDLES_DST_ADDR)) {103BIO_free(in);104BIO_free(out);105goto end;106}107SSL_set_bio(server, in, out);108SSL_set_accept_state(server);109110for (;;) {111size_t size;112uint64_t nxtpktms = 0;113OSSL_TIME nxtpkt = ossl_time_zero(), nxttimeout;114int isinf, ret = 0;115116if (len >= 2) {117if (len >= 5 && buf[0] == 0xff && buf[1] == 0xff) {118switch (buf[2]) {119case 0x00:120if (state == READING)121state = ACCEPTING_STREAM;122break;123case 0x01:124if (state == READING)125state = CREATING_STREAM;126break;127case 0x02:128if (state == READING)129state = SWAPPING_STREAM;130break;131default:132/* ignore */133break;134}135len -= 3;136buf += 3;137}138nxtpktms = buf[0] + (buf[1] << 8);139nxtpkt = ossl_time_add(fake_now, ossl_ms2time(nxtpktms));140len -= 2;141buf += 2;142}143144for (;;) {145switch (state) {146case HANDSHAKING:147ret = SSL_accept_connection(stream, 0) != NULL;148if (ret == 1)149state = READING;150break;151152case READING:153ret = SSL_read(stream, tmp, sizeof(tmp));154if (ret > 0) {155state = WRITING;156writelen = ret;157assert(writelen <= (int)sizeof(tmp));158}159break;160161case WRITING:162ret = SSL_write(stream, tmp, writelen);163if (ret > 0)164state = READING;165break;166167case ACCEPTING_STREAM:168state = READING;169ret = 1;170if (numstreams == OSSL_NELEM(allstreams)171|| SSL_get_accept_stream_queue_len(server) == 0)172break;173thisstream = numstreams;174stream = allstreams[numstreams++] = SSL_accept_stream(server, 0);175if (stream == NULL)176goto end;177break;178179case CREATING_STREAM:180state = READING;181ret = 1;182if (numstreams == OSSL_NELEM(allstreams))183break;184stream = SSL_new_stream(server, 0);185if (stream == NULL) {186/* Ignore, and go back to the previous stream */187stream = allstreams[thisstream];188break;189}190thisstream = numstreams;191allstreams[numstreams++] = stream;192break;193194case SWAPPING_STREAM:195state = READING;196ret = 1;197if (numstreams == 1)198break;199if (++thisstream == numstreams)200thisstream = 0;201stream = allstreams[thisstream];202break;203}204assert(stream != NULL);205assert(thisstream < numstreams);206if (ret <= 0) {207switch (SSL_get_error(stream, ret)) {208case SSL_ERROR_WANT_READ:209case SSL_ERROR_WANT_WRITE:210break;211default:212goto end;213}214}215216if (!SSL_get_event_timeout(server, &tv, &isinf))217goto end;218219if (isinf) {220fake_now = nxtpkt;221break;222} else {223nxttimeout = ossl_time_add(fake_now,224ossl_time_from_timeval(tv));225if (len > 3 && ossl_time_compare(nxttimeout, nxtpkt) >= 0) {226fake_now = nxtpkt;227break;228}229fake_now = nxttimeout;230}231}232233if (len <= 3)234break;235236size = buf[0] + (buf[1] << 8);237if (size > len - 2)238break;239240if (size > 0)241BIO_write(in, buf + 2, size);242len -= size + 2;243buf += size + 2;244}245end:246for (i = 0; i < numstreams; i++)247SSL_free(allstreams[i]);248ERR_clear_error();249SSL_CTX_free(ctx);250251return 0;252}253254void FuzzerCleanup(void)255{256FuzzerClearRand();257}258259260