Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QUIC: LCIDM #22673

Closed
wants to merge 12 commits into from
16 changes: 16 additions & 0 deletions doc/designs/quic-design/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ may be maintained at a given time. See `quic_record_rx.h` for details.

**KU:** Key update. See also TXKU, RXKU.

**LCID:** Local CID. Refers to a CID which will be recognised as identifying a
connection if found in the DCID field of an incoming packet. See also RCID.

**LCIDM:** Local CID Manager. Tracks LCIDs which have been advertised to a peer.
See also RCIDM.

**Locally-initiated:** Refers to a QUIC stream which was initiated by the local
application rather than the remote peer.

Expand Down Expand Up @@ -121,6 +127,10 @@ in which API calls can be made on different threads.
**MSST:** Multi-stream single-thread. Refers to a type of multi-stream QUIC
usage in which API calls must not be made concurrently.

**ODCID:** Original Destination CID. This is the DCID found in the first Initial
packet sent by a client, and is used to generate the secrets for encrypting
Initial packets. It is only used temporarily.

**PN:** Packet number. Most QUIC packet types have a packet number (PN); see RFC
9000.

Expand Down Expand Up @@ -165,6 +175,12 @@ not part of the APL. An XSO wraps a QUIC_STREAM once that stream is exposed as
an API object. As such, a `QUIC_CONNECTION` is to a `QUIC_CHANNEL` what a
`QUIC_XSO` is to a `QUIC_STREAM`.

**RCID:** Remote CID. Refers to a CID which has been provided to us by a peer
and which we can place in the DCID field of an outgoing packet. See also LCID.

**RCIDM:** Remote CID Manager. Tracks RCIDs which have been provided to us by a
peer. See also LCIDM.

**REGEN:** A strategy for regenerating lost frames. This strategy regenerates
the frame from canonical data sources without having to store a copy of the
frame which was transmitted. See FIFM design document for details.
Expand Down
12 changes: 10 additions & 2 deletions fuzz/build.info
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
ENDIF

IF[{- !$disabled{"quic"} -}]
PROGRAMS{noinst}=quic-client quic-srtm
PROGRAMS{noinst}=quic-client quic-srtm quic-lcidm
ENDIF

SOURCE[asn1]=asn1.c driver.c fuzz_rand.c
Expand Down Expand Up @@ -101,6 +101,10 @@ IF[{- !$disabled{"fuzz-afl"} || !$disabled{"fuzz-libfuzzer"} -}]
INCLUDE[quic-srtm]=../include {- $ex_inc -}
DEPEND[quic-srtm]=../libcrypto.a ../libssl.a {- $ex_lib -}

SOURCE[quic-lcidm]=quic-lcidm.c driver.c fuzz_rand.c
INCLUDE[quic-lcidm]=../include {- $ex_inc -}
DEPEND[quic-lcidm]=../libcrypto.a ../libssl.a {- $ex_lib -}

SOURCE[server]=server.c driver.c fuzz_rand.c
INCLUDE[server]=../include {- $ex_inc -}
DEPEND[server]=../libcrypto ../libssl {- $ex_lib -}
Expand Down Expand Up @@ -132,7 +136,7 @@ IF[{- !$disabled{tests} -}]
ENDIF

IF[{- !$disabled{"quic"} -}]
PROGRAMS{noinst}=quic-client-test quic-srtm-test
PROGRAMS{noinst}=quic-client-test quic-srtm-test quic-lcidm-test
ENDIF

SOURCE[asn1-test]=asn1.c test-corpus.c fuzz_rand.c
Expand Down Expand Up @@ -204,6 +208,10 @@ IF[{- !$disabled{tests} -}]
INCLUDE[quic-srtm-test]=../include
DEPEND[quic-srtm-test]=../libcrypto.a ../libssl.a

SOURCE[quic-lcidm-test]=quic-lcidm.c test-corpus.c fuzz_rand.c
INCLUDE[quic-lcidm-test]=../include
DEPEND[quic-lcidm-test]=../libcrypto.a ../libssl.a

SOURCE[server-test]=server.c test-corpus.c fuzz_rand.c
INCLUDE[server-test]=../include
DEPEND[server-test]=../libcrypto ../libssl
Expand Down
180 changes: 180 additions & 0 deletions fuzz/quic-lcidm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* https://www.openssl.org/source/license.html
* or in the file LICENSE in the source distribution.
*/

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/bio.h>
#include "fuzzer.h"
#include "internal/quic_lcidm.h"
#include "internal/packet.h"

int FuzzerInitialize(int *argc, char ***argv)
{
FuzzerSetRand();
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_ASYNC, NULL);
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
ERR_clear_error();
return 1;
}

/*
* Fuzzer input "protocol":
* Big endian
* u8(LCID length)
* Zero or more of:
* ENROL_ODCID u0(0x00) u64(opaque) u8(cidl):cid
hlandau marked this conversation as resolved.
Show resolved Hide resolved
* RETIRE_ODCID u8(0x01) u64(opaque)
* GENERATE_INITIAL u8(0x02) u64(opaque)
* GENERATE u8(0x03) u64(opaque)
* RETIRE u8(0x04) u64(opaque) u64(retire_prior_to)
* CULL u8(0x05) u64(opaque)
* LOOKUP u8(0x06) u8(cidl):cid
*/

enum {
CMD_ENROL_ODCID,
CMD_RETIRE_ODCID,
CMD_GENERATE_INITIAL,
CMD_GENERATE,
CMD_RETIRE,
CMD_CULL,
CMD_LOOKUP
};

static int get_cid(PACKET *pkt, QUIC_CONN_ID *cid)
{
unsigned int cidl;

if (!PACKET_get_1(pkt, &cidl)
|| cidl > QUIC_MAX_CONN_ID_LEN
|| !PACKET_copy_bytes(pkt, cid->id, cidl))
return 0;

cid->id_len = (unsigned char)cidl;
return 1;
}

int FuzzerTestOneInput(const uint8_t *buf, size_t len)
{
int rc = 0;
QUIC_LCIDM *lcidm = NULL;
PACKET pkt;
uint64_t arg_opaque, arg_retire_prior_to, seq_num_out;
unsigned int cmd, lcidl;
QUIC_CONN_ID arg_cid, cid_out;
OSSL_QUIC_FRAME_NEW_CONN_ID ncid_frame;
int did_retire;
void *opaque_out;

if (!PACKET_buf_init(&pkt, buf, len))
goto err;

if (!PACKET_get_1(&pkt, &lcidl)
|| lcidl > QUIC_MAX_CONN_ID_LEN) {
rc = -1;
goto err;
}

if ((lcidm = ossl_quic_lcidm_new(NULL, lcidl)) == NULL) {
rc = -1;
goto err;
}

while (PACKET_remaining(&pkt) > 0) {
if (!PACKET_get_1(&pkt, &cmd))
goto err;

switch (cmd) {
case CMD_ENROL_ODCID:
hlandau marked this conversation as resolved.
Show resolved Hide resolved
if (!PACKET_get_net_8(&pkt, &arg_opaque)
|| !get_cid(&pkt, &arg_cid)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_enrol_odcid(lcidm, (void *)(uintptr_t)arg_opaque,
&arg_cid);
break;

case CMD_RETIRE_ODCID:
if (!PACKET_get_net_8(&pkt, &arg_opaque)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_retire_odcid(lcidm, (void *)(uintptr_t)arg_opaque);
break;

case CMD_GENERATE_INITIAL:
if (!PACKET_get_net_8(&pkt, &arg_opaque)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_generate_initial(lcidm, (void *)(uintptr_t)arg_opaque,
&cid_out);
break;

case CMD_GENERATE:
if (!PACKET_get_net_8(&pkt, &arg_opaque)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_generate(lcidm, (void *)(uintptr_t)arg_opaque,
&ncid_frame);
break;

case CMD_RETIRE:
if (!PACKET_get_net_8(&pkt, &arg_opaque)
|| !PACKET_get_net_8(&pkt, &arg_retire_prior_to)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_retire(lcidm, (void *)(uintptr_t)arg_opaque,
arg_retire_prior_to,
NULL, &cid_out,
&seq_num_out, &did_retire);
break;

case CMD_CULL:
if (!PACKET_get_net_8(&pkt, &arg_opaque)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_cull(lcidm, (void *)(uintptr_t)arg_opaque);
break;

case CMD_LOOKUP:
if (!get_cid(&pkt, &arg_cid)) {
rc = -1;
goto err;
}

ossl_quic_lcidm_lookup(lcidm, &arg_cid, &seq_num_out, &opaque_out);
break;

default:
rc = -1;
goto err;
}
}

err:
ossl_quic_lcidm_free(lcidm);
return rc;
}

void FuzzerCleanup(void)
{
FuzzerClearRand();
}