Development discussion of WireGuard
 help / color / mirror / Atom feed
* another thread on montonic counter alternatives
@ 2021-08-08 22:33 Jason A. Donenfeld
  2021-08-08 23:18 ` Karolin Varner
  0 siblings, 1 reply; 4+ messages in thread
From: Jason A. Donenfeld @ 2021-08-08 22:33 UTC (permalink / raw)
  To: WireGuard mailing list; +Cc: Karolin Varner, noise, Ivan Labáth

Hi folks,

We've had this discussion a few times in various forms, but it's come
up again recently, with Karolin Varner (CC'd) emailing me with some
fresh enthusiasm about the problem space, so I thought this might be
something worth discussing again, perhaps this time with some input
from the Noise mailing list.

NoiseIK is 1-RTT, so WireGuard sticks a timestamp in the first message
to prevent replay attacks. Responders reject packets with timestamps
that are larger than the last one received. If a responder reboots,
there's subsequently no session to disrupt with a replay anyway, so
it's not an issue. Generally this works well, provided initiators have
a reliable monotonic counter. Generally timestamps are considered
reliable-enough monotonic counters. Issues with this begin from two
angles:

Angle 1) Embedded devices without a battery powered RTC that want to
use WireGuard to bootstrap have a chicken & egg problem.
Angle 2) Initiators that are using the old, crusty, and insecure NTP
protocol can have their time hijacked.

Angle 2 presents some interesting possibilities. An adversary who sets
somebody's time backwards can prevent them from connecting until their
time is set right again. Adversaries who set somebody's time forward,
say, to the maximum TAI64N value, and then subsequently have an
initiator send an initiation message, can then render that initiator's
static private key forever useless, since that future timestamp can
always be replayed, and will always set the responder's greatest-yet
value to that maximum. So, if your NTP is hijacked, your key is
forever DoS'd.

We've talked about a few solutions before to this. They all have
various pitfalls.

Idea 0) Insist people don't use NTP but rather some authenticated
alternative. Insist people have battery-powered RTCs.

Idea 1) Store a monotonic counter on disk, and just increment it by 1,
or even some random value bounded far below the limit, on each
handshake. The downside is this relies on storage that doesn't wear
out and is always available.

Idea 2) For a given system boot, store in memory the time of the first
handshake, and then increment that timestamp by 1 on each handshake.
The problem is figuring out when to sample that initial golden
timestamp. And it doesn't actually solve Angle 2, because that initial
golden timestamp still might wind up NTP sync'd at some point.

Idea 3) Insist people who must use NTP disable large jumps. This has
the same issue as Idea 2, in that the bootstrapping timestamp is still
an issue.

Idea 4) Require the responder to also have a synchronized clock and
reject handshakes that are too far into the future. This might
alleviate Angle 2 to a large degree but it causes big issues for Angle
1, potentially.

Other clever ideas?

Jason

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: another thread on montonic counter alternatives
  2021-08-08 22:33 another thread on montonic counter alternatives Jason A. Donenfeld
@ 2021-08-08 23:18 ` Karolin Varner
  2021-08-10  0:09   ` Trevor Perrin
  0 siblings, 1 reply; 4+ messages in thread
From: Karolin Varner @ 2021-08-08 23:18 UTC (permalink / raw)
  To: wireguard; +Cc: noise, labo

Good evening,

I can see this has been copiously discussed…

On 8/9/21 12:33 AM, Jason A. Donenfeld wrote:
> Angle 2 presents some interesting possibilities. An adversary who sets
> somebody's time backwards can prevent them from connecting until their
> time is set right again. Adversaries who set somebody's time forward,
> say, to the maximum TAI64N value, and then subsequently have an
> initiator send an initiation message, can then render that initiator's
> static private key forever useless, since that future timestamp can
> always be replayed, and will always set the responder's greatest-yet
> value to that maximum. So, if your NTP is hijacked, your key is
> forever DoS'd.

In my view this presents a major problem. I don't have data on this, but I think this is a common setup.
Mine was vulnerable and if you didn't take care to prevent this yours is probably too.

At the very least there should be a bold, red warning on the webpage "do not use WG with NTP".

> Other clever ideas?

0) Just send the value of tsmax to the peer? This basically surmounts to falling back to fully interactive but is a minimal change?
1) Pick a random time stamp/a time stamp based on the peers `MAC(cookie_secret, IP | Port)` and accept that for a single time only. This also basically surmounts to an interactive handshake with minimal changes.

Is changing the protocol an option? Two options for that:

2) Fall back to an interactive handshake using cookies. Define a protocol version two, mandate that in V2 the cookie must be mixed into the handshake hash. Assign a cookie in case of timestamp failure.
3) Use a stateless responder; forego the timestamp entirely. Instead of storing the handshake state (ck, h, eskr) locally, they could be encrypted with a random key and included in the second message. This way, there is no responder state an attacker could interrupt.

2) is 1-RTT in the normal case and 2-RTT with the attack agains the counter. 3) is always 1-RTT and always interactive but requires a response for replayed old handshakes.

Jason pointed out, that it would be preferable to use a Noise-XK handshake which is a standard fully-interactive handshake but 1.5-RTT. I was assuming 1-RTT-ness was a necessity.
Of course, coming up with a new handshake is…generally foolish and even though both my proposal technially fit into the noise-IK pattern, noise-XK certainly is more trustworthy.

Noise XK could also be used as a fallback only, but this would considerably increase complexity.

As far as mitigations go:

a) Do not drop handshake state after three minutes, just ratchet the key `MixKey(empty)` so the attack can not disrupt active sessions.
b) Jason's angle 4 but with a flag. A command line switch "interpret counter as timestamp and reject timestamps off by more than 20m".

Best,
Karolin

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: another thread on montonic counter alternatives
  2021-08-08 23:18 ` Karolin Varner
@ 2021-08-10  0:09   ` Trevor Perrin
  2021-08-10  7:53     ` Karolin Varner
  0 siblings, 1 reply; 4+ messages in thread
From: Trevor Perrin @ 2021-08-10  0:09 UTC (permalink / raw)
  To: Karolin Varner; +Cc: wireguard, noise, labo

On Sun, Aug 8, 2021 at 5:04 PM Karolin Varner <karo@cupdev.net> wrote:
>
> 2) Fall back to an interactive handshake using cookies. Define a protocol version two, mandate that in V2 the cookie must be mixed into the handshake hash. Assign a cookie in case of timestamp failure.

That could be deployed in a backwards-compatible way, I think?  If the
client's V1 handshake is rejected due to an old timestamp, the client
is given the cookie which enables it to do the V2 handshake?


> Jason pointed out, that it would be preferable to use a Noise-XK handshake which is a standard fully-interactive handshake but 1.5-RTT. I was assuming 1-RTT-ness was a necessity.
> Of course, coming up with a new handshake is…generally foolish and even though both my proposal technially fit into the noise-IK pattern, noise-XK certainly is more trustworthy.

I thought the goal of IK here was: server only stores state if client
is authenticated.  And the goal of timestamp was: replayed messages
can't invalidate an existing session state.

If those are still the requirements I'm not sure that XK meets them.
XK has better identity hiding (only reveals the client's identity
after forward-secrecy is negotiated), but that trades off against the
requirement that unauthenticated clients can't cause servers to store
state.  (Unless you put the state in a cookie, I suppose - which you
also suggested...)

Trevor

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: another thread on montonic counter alternatives
  2021-08-10  0:09   ` Trevor Perrin
@ 2021-08-10  7:53     ` Karolin Varner
  0 siblings, 0 replies; 4+ messages in thread
From: Karolin Varner @ 2021-08-10  7:53 UTC (permalink / raw)
  To: Trevor Perrin; +Cc: wireguard, noise, labo

On 8/10/21 2:09 AM, Trevor Perrin wrote:
> On Sun, Aug 8, 2021 at 5:04 PM Karolin Varner <karo@cupdev.net> wrote:
>>
>> 2) Fall back to an interactive handshake using cookies. Define a protocol version two, mandate that in V2 the cookie must be mixed into the handshake hash. Assign a cookie in case of timestamp failure.
> 
> That could be deployed in a backwards-compatible way, I think?  If the
> client's V1 handshake is rejected due to an old timestamp, the client
> is given the cookie which enables it to do the V2 handshake?

Yes!
I was thinking InitHello with a flag set in the reserved bytes, peer responds with cookie and a compatibility flag set as well.
The flag would be ignored by legacy responders, these would also respond with the flag set to zero in cookie replies so the initiator knows not to use V2 when resending InitHello with a cookie.
Peers generating messages without a cookie should skip the cookie mixing step (not mix {0}^n) so the message can be processed by legacy peers and modern ones alike.

There may be non-standard implementations which assert the reserved bytes to be {0}^3,
so sending a one-time-counter using an entirely new packet type might be even more compatible. Such a message would be entirely ignored by all but the worst implementations.

Karolin

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-08-10  7:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-08 22:33 another thread on montonic counter alternatives Jason A. Donenfeld
2021-08-08 23:18 ` Karolin Varner
2021-08-10  0:09   ` Trevor Perrin
2021-08-10  7:53     ` Karolin Varner

Development discussion of WireGuard

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.vuxu.org/wireguard/0 wireguard/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 wireguard wireguard/ https://inbox.vuxu.org/wireguard \
		wireguard@lists.zx2c4.com
	public-inbox-index wireguard

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.vuxu.org/vuxu.archive.wireguard


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git