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