Re: Too many GREASE codepoints

Kazuho Oku <kazuhooku@gmail.com> Wed, 18 November 2020 00:38 UTC

Return-Path: <kazuhooku@gmail.com>
X-Original-To: quic@ietfa.amsl.com
Delivered-To: quic@ietfa.amsl.com
Received: from localhost (localhost [127.0.0.1]) by ietfa.amsl.com (Postfix) with ESMTP id BF32C3A1119 for <quic@ietfa.amsl.com>; Tue, 17 Nov 2020 16:38:35 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.097
X-Spam-Level:
X-Spam-Status: No, score=-2.097 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no
Authentication-Results: ietfa.amsl.com (amavisd-new); dkim=pass (2048-bit key) header.d=gmail.com
Received: from mail.ietf.org ([4.31.198.44]) by localhost (ietfa.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id HVDIGiZLiSYV for <quic@ietfa.amsl.com>; Tue, 17 Nov 2020 16:38:33 -0800 (PST)
Received: from mail-ej1-x631.google.com (mail-ej1-x631.google.com [IPv6:2a00:1450:4864:20::631]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ietfa.amsl.com (Postfix) with ESMTPS id 40CC93A1125 for <quic@ietf.org>; Tue, 17 Nov 2020 16:38:31 -0800 (PST)
Received: by mail-ej1-x631.google.com with SMTP id a16so301104ejj.5 for <quic@ietf.org>; Tue, 17 Nov 2020 16:38:31 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=iXM6znF5we7r6HGGnbLEhxERKbW8qKBj+8lRbWCuvNM=; b=c+QIhc3e3mPB7+bqBo4k3THc/bwMy7Ua5qAEvWy81wyg9ZvSHuit5Smk48DupW5Xkv az0720F4WKhvoIoTe+bUsaqWmIgv/gvDuX3z3kO07tuSLqzxCT4d2ppqSKiBrycgdWS9 KfYMBcA8pUVEbS09Aoh5vr1DAfGMA21t4ueM+LBmcNJUmT5pwb9uyWuxtTTaJjucEtl+ htXXaoCP5vLjWJbHIcQujcgTLEOQTeYRj2NXV16CNAYN4QsEVdeh2JZp+GtJxFuMy3Uk NOUSW+jyKfiwb78w8h630YIZYcRf3B68H1CuSGim0TFpox12mH6M1DYEmhySJmm42TR3 nYzg==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=iXM6znF5we7r6HGGnbLEhxERKbW8qKBj+8lRbWCuvNM=; b=Gvf6evaeQpb0Qg/I73SewEFef+IkLRkzX8i5MvD1jGQECcJ/bknRmqECKLJjLVqVRu jQBbSIldB6tsoPRml3bpZQnkIqMXhpeCiAMHKz554/1pjZYJemuurwskGhxEM3VahXWU Xn+u396LGIjleTzUJUsCOo75zbOFa2jCTKK8uWzJvXl4Oi7vPc7VzB5dXnUjIy9mvLGG tcKxHzbZb024PS7xsmfhwpN6pNiGG3yDgTSwypYdXm3qB9NhPpbdfkqd5U0YCw+5SYaT URpwtwSjs6YLQ1It3XDkNtRgNUOISSHTcSFMPBQ8maxlIP+R6KmwVy00Ds7SwqGKqTSt HXRQ==
X-Gm-Message-State: AOAM533mZzCXIqgZKrs99/U9o1V7FemaLxKHiH5zn00QFL2AL6VM5lKW zyzUn6hn6J5sW8MCYlUx8ayBVrYm8GM0cuzgupPBmkfBZf3oMA==
X-Google-Smtp-Source: ABdhPJzsIpxLL65fonzxGCRJfGQyJblPNdp69+IUsPsQLEdMLMXK0JgjrOcILOridUhBKC/Pd93LyB0GXLJvpn2Vc+M=
X-Received: by 2002:a17:906:a43:: with SMTP id x3mr21827477ejf.197.1605659909768; Tue, 17 Nov 2020 16:38:29 -0800 (PST)
MIME-Version: 1.0
References: <59a19e58-ced4-4a38-89da-e9441df162fb@www.fastmail.com>
In-Reply-To: <59a19e58-ced4-4a38-89da-e9441df162fb@www.fastmail.com>
From: Kazuho Oku <kazuhooku@gmail.com>
Date: Wed, 18 Nov 2020 09:38:18 +0900
Message-ID: <CANatvzxJ0Y5xOo+RAWAoVk-gzSrdjAOWk-iNTSQUVg0CTH2W=w@mail.gmail.com>
Subject: Re: Too many GREASE codepoints
To: Martin Thomson <mt@lowentropy.net>
Cc: IETF QUIC WG <quic@ietf.org>
Content-Type: multipart/alternative; boundary="0000000000008d4bb105b456d42f"
Archived-At: <https://mailarchive.ietf.org/arch/msg/quic/II7yfdoY7bln2Xe_O6KV6F9XMSg>
X-BeenThere: quic@ietf.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Main mailing list of the IETF QUIC working group <quic.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/options/quic>, <mailto:quic-request@ietf.org?subject=unsubscribe>
List-Archive: <https://mailarchive.ietf.org/arch/browse/quic/>
List-Post: <mailto:quic@ietf.org>
List-Help: <mailto:quic-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/quic>, <mailto:quic-request@ietf.org?subject=subscribe>
X-List-Received-Date: Wed, 18 Nov 2020 00:38:36 -0000

2020年11月18日(水) 8:41 Martin Thomson <mt@lowentropy.net>:

> (I've been meaning to write this for a few days, but the IANA review
> prompted me to sit down and work through it.)
>
> I have come to believe that we are reserving too many codepoints for
> greasing.
>
> The greasing function we currently use is 27+N*31.  That's about 2^57
> values.  148764065110560896 by my estimation.
>
> The waste I can tolerate.  This is a very large number, but it leaves
> plenty of values free for use.  The problem is that the odds of collision
> are too low.
>
> This problem was highlighted when draft-iyengar-quic-delayed-ack-02 chose
> a greased codepoint.  The failure mode there is terrible: occasionally an
> implementation will generate a greased value that collides with this
> value.  If an implementation of that draft encounters that collision it
> will fail.  It will probably fail when trying to parse the transport
> parameter, but it could instead fail when it receives the frame.
> Alternatively, is also plausible that an implementation of the draft could
> include a greased value with the same codepoint, which would be similarly
> bad.  Such failures are virtually impossible to reproduce and unless you
> are lucky enough to have good logging, you might have trouble catching the
> reason for the error.
>
> The odds that an implementation of that draft would encounter a peer who
> used a greased codepoint with the same value is minuscule.  There are
> around 2^57 valid greasing values, so even if every connection ever
> included greased values, the odds of a given connection containing that
> value is tiny. (Coincidentally, this is the same as the probability we
> allow for an attacker to attack the packet protection AEAD.)
>
> I think that we want a higher risk of collision than that.  Then mistakes
> like this will result in a higher probability of failure when deployed.
> Ideally, failures will be discovered in testing.
>
> The reason we have a non-trivial number of reserved codepoints is to avoid
> having implementations that filter out these reserved values by just
> enumerating them.  However, for that we don't need so many reserved
> values.  Even as little as 1000 will create a disincentive to tabulate the
> values.  That many would add a large 8k table to a simple implementation.
>
> If we were to select 1000 (or 1024) values in a way that is relatively
> simple to generate from a random number, then that would be better than the
> current situation.
>
> So I'm going to propose that we define a new function that takes a 10-bit
> random value and produces a greasing codepoint.  This can be used to
> produce a greasing codepoint.  I have two requirements:
>
> * It should be a tiny bit more complex to implement a function that tests
> a value for whether it is reserved.  The current scheme is easy to filter.
> (X - 27) % 31 == 0 isn't much code to write.
>
> * The scheme needs to produce values that encode to 1, 2, and 4 bytes in
> varints with reasonable probability.  An even distribution over 2^62 with
> 1024 values has a gap of 2^52 between each value, which means that 2 byte
> and 4 byte values aren't likely to be represented.
>
> The function I've been thinking of looks like this:
>
> def grease(n):
>     v = 27
>     i = 1
>     while n > 0:
>         v = (v << i) | (n & 1)
>         i = i + 1
>         n = n >> 1
>     return v
>
> This is bit spreader, taking the bits of the random value and adding
> progressively more space between each bit.
>
> When passed 0x3ff, the resulting value is the 60-bit binary value:
> 0b110111010010001000010000010000001000000010000000010000000001.  Smaller
> values result in different 1 bits being turned off.  If it is passed 0x1ff,
> it produces the shorter 50-bit value of
> 0b11011101001000100001000001000000100000001000000001.
>
> The result is two values that encode to 1 byte, 14 values that encode to 2
> bytes, 48 values that encode to 4 bytes, with the remaining 960 values
> encoding to 8 bytes.
>

This is an interesting proposal, though I am not sure how much it helps.

The argument for the proposed scheme is that the chance of collision
becomes negligible. However, the proposal tries to have higher probability
for small numbers.

If we are to reduce the chance of collision, I think we should simply use
something like (X + INT32_MAX - 4) % INT32_MAX == 0 or something, and also
encourage greasing endpoints to use verbose notations for varints (e.g.,
use 0xc000000000000001 to represent 1). I think that the latter rule would
enforce receivers to decode varints before processing the input, and then,
we do not need to have higher probability for small numbers.

That said, I am not sure if we have to change the greasing scheme at this
point. When we noticed that the ack-delay extension was colliding with the
greasing ID, I created the PR below, that detects such misuse at compile
time:

    https://github.com/h2o/quicly/pull/416

It might just be sufficient if other endpoints implement this type of
detection scheme as well.



> Detecting this is fairly easy, but also probably not worth writing out the
> code to do so.  This could be made considerably harder by flipping more
> than one bit at a time.  For example, `v = (v << i) ^ ((n & 1) * 19)`.
>
> What do people think?  Is this a change we could tolerate?  Or is my logic
> faulty here in some way?
>
>

-- 
Kazuho Oku