1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License");
5*e7be843bSPierre Pronchery * you may not use this file except in compliance with the License.
6*e7be843bSPierre Pronchery * You may obtain a copy of the License at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery * or in the file LICENSE in the source distribution.
9*e7be843bSPierre Pronchery */
10*e7be843bSPierre Pronchery
11*e7be843bSPierre Pronchery #include <openssl/ssl.h>
12*e7be843bSPierre Pronchery #include <openssl/err.h>
13*e7be843bSPierre Pronchery #include <openssl/bio.h>
14*e7be843bSPierre Pronchery #include "fuzzer.h"
15*e7be843bSPierre Pronchery #include "internal/quic_rcidm.h"
16*e7be843bSPierre Pronchery #include "internal/packet.h"
17*e7be843bSPierre Pronchery
FuzzerInitialize(int * argc,char *** argv)18*e7be843bSPierre Pronchery int FuzzerInitialize(int *argc, char ***argv)
19*e7be843bSPierre Pronchery {
20*e7be843bSPierre Pronchery FuzzerSetRand();
21*e7be843bSPierre Pronchery OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);
22*e7be843bSPierre Pronchery OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
23*e7be843bSPierre Pronchery ERR_clear_error();
24*e7be843bSPierre Pronchery return 1;
25*e7be843bSPierre Pronchery }
26*e7be843bSPierre Pronchery
27*e7be843bSPierre Pronchery /*
28*e7be843bSPierre Pronchery * Fuzzer input "protocol":
29*e7be843bSPierre Pronchery * Big endian
30*e7be843bSPierre Pronchery * Zero or more of:
31*e7be843bSPierre Pronchery * RESET_WITH_ODCID u8(0x00) u8(cidl):cid
32*e7be843bSPierre Pronchery * RESET_WITHOUT_ODCID u8(0x01)
33*e7be843bSPierre Pronchery * (free and reallocate)
34*e7be843bSPierre Pronchery * ADD_FROM_INITIAL u8(0x02) u8(cidl):cid
35*e7be843bSPierre Pronchery * ADD_FROM_SERVER_RETRY u8(0x03) u8(cidl):cid
36*e7be843bSPierre Pronchery * ADD_FROM_NCID u8(0x04) u64(seq_num)
37*e7be843bSPierre Pronchery * u64(retire_prior_to) u8(cidl):cid
38*e7be843bSPierre Pronchery * ON_HANDSHAKE_COMPLETE u8(0x05)
39*e7be843bSPierre Pronchery * ON_PACKET_SENT u8(0x06) u64(num_pkt)
40*e7be843bSPierre Pronchery * REQUEST_ROLL u8(0x07)
41*e7be843bSPierre Pronchery * POP_RETIRE_SEQ_NUM u8(0x08)
42*e7be843bSPierre Pronchery * PEEK_RETIRE_SEQ_NUM u8(0x09)
43*e7be843bSPierre Pronchery * GET_PREFERRED_TX_DCID u8(0x0A)
44*e7be843bSPierre Pronchery * GET_PREFERRED_TX_DCID_CHANGED u8(0x0B) u8(clear)
45*e7be843bSPierre Pronchery */
46*e7be843bSPierre Pronchery
47*e7be843bSPierre Pronchery enum {
48*e7be843bSPierre Pronchery CMD_RESET_WITH_ODCID,
49*e7be843bSPierre Pronchery CMD_RESET_WITHOUT_ODCID,
50*e7be843bSPierre Pronchery CMD_ADD_FROM_INITIAL,
51*e7be843bSPierre Pronchery CMD_ADD_FROM_SERVER_RETRY,
52*e7be843bSPierre Pronchery CMD_ADD_FROM_NCID,
53*e7be843bSPierre Pronchery CMD_ON_HANDSHAKE_COMPLETE,
54*e7be843bSPierre Pronchery CMD_ON_PACKET_SENT,
55*e7be843bSPierre Pronchery CMD_REQUEST_ROLL,
56*e7be843bSPierre Pronchery CMD_POP_RETIRE_SEQ_NUM,
57*e7be843bSPierre Pronchery CMD_PEEK_RETIRE_SEQ_NUM,
58*e7be843bSPierre Pronchery CMD_GET_PREFERRED_TX_DCID,
59*e7be843bSPierre Pronchery CMD_GET_PREFERRED_TX_DCID_CHANGED
60*e7be843bSPierre Pronchery };
61*e7be843bSPierre Pronchery
get_cid(PACKET * pkt,QUIC_CONN_ID * cid)62*e7be843bSPierre Pronchery static int get_cid(PACKET *pkt, QUIC_CONN_ID *cid)
63*e7be843bSPierre Pronchery {
64*e7be843bSPierre Pronchery unsigned int cidl;
65*e7be843bSPierre Pronchery
66*e7be843bSPierre Pronchery if (!PACKET_get_1(pkt, &cidl)
67*e7be843bSPierre Pronchery || cidl > QUIC_MAX_CONN_ID_LEN
68*e7be843bSPierre Pronchery || !PACKET_copy_bytes(pkt, cid->id, cidl))
69*e7be843bSPierre Pronchery return 0;
70*e7be843bSPierre Pronchery
71*e7be843bSPierre Pronchery cid->id_len = (unsigned char)cidl;
72*e7be843bSPierre Pronchery return 1;
73*e7be843bSPierre Pronchery }
74*e7be843bSPierre Pronchery
FuzzerTestOneInput(const uint8_t * buf,size_t len)75*e7be843bSPierre Pronchery int FuzzerTestOneInput(const uint8_t *buf, size_t len)
76*e7be843bSPierre Pronchery {
77*e7be843bSPierre Pronchery int rc = 0;
78*e7be843bSPierre Pronchery QUIC_RCIDM *rcidm = NULL;
79*e7be843bSPierre Pronchery PACKET pkt;
80*e7be843bSPierre Pronchery uint64_t seq_num_out, arg_num_pkt;
81*e7be843bSPierre Pronchery unsigned int cmd, arg_clear;
82*e7be843bSPierre Pronchery QUIC_CONN_ID arg_cid, cid_out;
83*e7be843bSPierre Pronchery OSSL_QUIC_FRAME_NEW_CONN_ID ncid_frame;
84*e7be843bSPierre Pronchery
85*e7be843bSPierre Pronchery if (!PACKET_buf_init(&pkt, buf, len))
86*e7be843bSPierre Pronchery goto err;
87*e7be843bSPierre Pronchery
88*e7be843bSPierre Pronchery if ((rcidm = ossl_quic_rcidm_new(NULL)) == NULL)
89*e7be843bSPierre Pronchery goto err;
90*e7be843bSPierre Pronchery
91*e7be843bSPierre Pronchery while (PACKET_remaining(&pkt) > 0) {
92*e7be843bSPierre Pronchery if (!PACKET_get_1(&pkt, &cmd))
93*e7be843bSPierre Pronchery goto err;
94*e7be843bSPierre Pronchery
95*e7be843bSPierre Pronchery switch (cmd) {
96*e7be843bSPierre Pronchery case CMD_RESET_WITH_ODCID:
97*e7be843bSPierre Pronchery if (!get_cid(&pkt, &arg_cid)) {
98*e7be843bSPierre Pronchery rc = -1;
99*e7be843bSPierre Pronchery goto err;
100*e7be843bSPierre Pronchery }
101*e7be843bSPierre Pronchery
102*e7be843bSPierre Pronchery ossl_quic_rcidm_free(rcidm);
103*e7be843bSPierre Pronchery
104*e7be843bSPierre Pronchery if ((rcidm = ossl_quic_rcidm_new(&arg_cid)) == NULL)
105*e7be843bSPierre Pronchery goto err;
106*e7be843bSPierre Pronchery
107*e7be843bSPierre Pronchery break;
108*e7be843bSPierre Pronchery
109*e7be843bSPierre Pronchery case CMD_RESET_WITHOUT_ODCID:
110*e7be843bSPierre Pronchery ossl_quic_rcidm_free(rcidm);
111*e7be843bSPierre Pronchery
112*e7be843bSPierre Pronchery if ((rcidm = ossl_quic_rcidm_new(NULL)) == NULL)
113*e7be843bSPierre Pronchery goto err;
114*e7be843bSPierre Pronchery
115*e7be843bSPierre Pronchery break;
116*e7be843bSPierre Pronchery
117*e7be843bSPierre Pronchery case CMD_ADD_FROM_INITIAL:
118*e7be843bSPierre Pronchery if (!get_cid(&pkt, &arg_cid)) {
119*e7be843bSPierre Pronchery rc = -1;
120*e7be843bSPierre Pronchery goto err;
121*e7be843bSPierre Pronchery }
122*e7be843bSPierre Pronchery
123*e7be843bSPierre Pronchery ossl_quic_rcidm_add_from_initial(rcidm, &arg_cid);
124*e7be843bSPierre Pronchery break;
125*e7be843bSPierre Pronchery
126*e7be843bSPierre Pronchery case CMD_ADD_FROM_SERVER_RETRY:
127*e7be843bSPierre Pronchery if (!get_cid(&pkt, &arg_cid)) {
128*e7be843bSPierre Pronchery rc = -1;
129*e7be843bSPierre Pronchery goto err;
130*e7be843bSPierre Pronchery }
131*e7be843bSPierre Pronchery
132*e7be843bSPierre Pronchery ossl_quic_rcidm_add_from_server_retry(rcidm, &arg_cid);
133*e7be843bSPierre Pronchery break;
134*e7be843bSPierre Pronchery
135*e7be843bSPierre Pronchery case CMD_ADD_FROM_NCID:
136*e7be843bSPierre Pronchery if (!PACKET_get_net_8(&pkt, &ncid_frame.seq_num)
137*e7be843bSPierre Pronchery || !PACKET_get_net_8(&pkt, &ncid_frame.retire_prior_to)
138*e7be843bSPierre Pronchery || !get_cid(&pkt, &ncid_frame.conn_id)) {
139*e7be843bSPierre Pronchery rc = -1;
140*e7be843bSPierre Pronchery goto err;
141*e7be843bSPierre Pronchery }
142*e7be843bSPierre Pronchery
143*e7be843bSPierre Pronchery ossl_quic_rcidm_add_from_ncid(rcidm, &ncid_frame);
144*e7be843bSPierre Pronchery break;
145*e7be843bSPierre Pronchery
146*e7be843bSPierre Pronchery case CMD_ON_HANDSHAKE_COMPLETE:
147*e7be843bSPierre Pronchery ossl_quic_rcidm_on_handshake_complete(rcidm);
148*e7be843bSPierre Pronchery break;
149*e7be843bSPierre Pronchery
150*e7be843bSPierre Pronchery case CMD_ON_PACKET_SENT:
151*e7be843bSPierre Pronchery if (!PACKET_get_net_8(&pkt, &arg_num_pkt)) {
152*e7be843bSPierre Pronchery rc = -1;
153*e7be843bSPierre Pronchery goto err;
154*e7be843bSPierre Pronchery }
155*e7be843bSPierre Pronchery
156*e7be843bSPierre Pronchery ossl_quic_rcidm_on_packet_sent(rcidm, arg_num_pkt);
157*e7be843bSPierre Pronchery break;
158*e7be843bSPierre Pronchery
159*e7be843bSPierre Pronchery case CMD_REQUEST_ROLL:
160*e7be843bSPierre Pronchery ossl_quic_rcidm_request_roll(rcidm);
161*e7be843bSPierre Pronchery break;
162*e7be843bSPierre Pronchery
163*e7be843bSPierre Pronchery case CMD_POP_RETIRE_SEQ_NUM:
164*e7be843bSPierre Pronchery ossl_quic_rcidm_pop_retire_seq_num(rcidm, &seq_num_out);
165*e7be843bSPierre Pronchery break;
166*e7be843bSPierre Pronchery
167*e7be843bSPierre Pronchery case CMD_PEEK_RETIRE_SEQ_NUM:
168*e7be843bSPierre Pronchery ossl_quic_rcidm_peek_retire_seq_num(rcidm, &seq_num_out);
169*e7be843bSPierre Pronchery break;
170*e7be843bSPierre Pronchery
171*e7be843bSPierre Pronchery case CMD_GET_PREFERRED_TX_DCID:
172*e7be843bSPierre Pronchery ossl_quic_rcidm_get_preferred_tx_dcid(rcidm, &cid_out);
173*e7be843bSPierre Pronchery break;
174*e7be843bSPierre Pronchery
175*e7be843bSPierre Pronchery case CMD_GET_PREFERRED_TX_DCID_CHANGED:
176*e7be843bSPierre Pronchery if (!PACKET_get_1(&pkt, &arg_clear)) {
177*e7be843bSPierre Pronchery rc = -1;
178*e7be843bSPierre Pronchery goto err;
179*e7be843bSPierre Pronchery }
180*e7be843bSPierre Pronchery
181*e7be843bSPierre Pronchery ossl_quic_rcidm_get_preferred_tx_dcid_changed(rcidm, arg_clear);
182*e7be843bSPierre Pronchery break;
183*e7be843bSPierre Pronchery
184*e7be843bSPierre Pronchery default:
185*e7be843bSPierre Pronchery rc = -1;
186*e7be843bSPierre Pronchery goto err;
187*e7be843bSPierre Pronchery }
188*e7be843bSPierre Pronchery }
189*e7be843bSPierre Pronchery
190*e7be843bSPierre Pronchery err:
191*e7be843bSPierre Pronchery ossl_quic_rcidm_free(rcidm);
192*e7be843bSPierre Pronchery return rc;
193*e7be843bSPierre Pronchery }
194*e7be843bSPierre Pronchery
FuzzerCleanup(void)195*e7be843bSPierre Pronchery void FuzzerCleanup(void)
196*e7be843bSPierre Pronchery {
197*e7be843bSPierre Pronchery FuzzerClearRand();
198*e7be843bSPierre Pronchery }
199