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 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 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 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 195 void FuzzerCleanup(void) 196 { 197 FuzzerClearRand(); 198 } 199