Re: [PATCH net-next v2] net: WireGuard secure network tunnel

From: Dmitry Vyukov
Date: Thu Dec 19 2019 - 09:30:18 EST


On Thu, Dec 19, 2019 at 12:38 PM Jason A. Donenfeld <Jason@xxxxxxxxx> wrote:
>
> On Thu, Dec 19, 2019 at 12:19 PM Dmitry Vyukov <dvyukov@xxxxxxxxxx> wrote:
> > > Ahh, cool, okay. Netlink, device creation, and basic packet structure
> > > is a good start. What about the crypto, though?
> >
> > It depends. What exactly we need there?
> > syzkaller uses comparison operand interception which allows it e.g. to
> > guess signatures/checksums in some cases.
>
> I don't think you'll have too much luck with WireGuard here. Fuzzing
> your way to a valid handshake message involves guessing the 4th
> preimage of some elliptic curve scalar multiplication, with some
> random/changing data mixed in there every time you make a new try.
> There's a condensed protocol description here which should be less bad
> to glance at than the academic paper:
> https://www.wireguard.com/protocol/#first-message-initiator-to-responder
> . The fuzzers I've written for the crypto bits of WireGuard always
> involve taking a complete handshake implementation and mutating things
> from there. So maybe the "outer packet" won't be too fruitful without
> a bunch of work. At the very least, we can generate packets that have
> the right field sizes and such, and that should test the first level
> of error cases I guess.

Yes, properly formed packets will probably require some procedural support.
I can't say right away which exactly extension mechanism in syzkaller
is the best for this.
But there is another one I forgot to mention - custom pseudo syscalls.
For the generic fuzzer engine they look like normal syscalls that
accept/return something:
https://github.com/google/syzkaller/blob/36650b4b2c942bc382314dce384d311fbadd1208/sys/linux/vnet.txt#L26
but the actual implementation is our custom C code that can do
anything (augment data, form packets, call multiple syscalls, take
result of one syscall, do something with it and use as argument for
another, etc):
https://github.com/google/syzkaller/blob/36650b4b2c942bc382314dce384d311fbadd1208/executor/common_linux.h#L972-L1023
These make doing a complex thing trivial for fuzzer, but the more is
hardcoded there, the less randomness we get from fuzzing (though that
presudo-syscall can also accept some additional randomness and use it
in some way).



> However, there's still a decent amount of surface on the "inner
> packet". For this, we can set up a pair of wireguard interfaces that
> are preconfigured to talk to each other (in common_linux.h, right? Or
> do you have some Go file that'd be easier to do that initialization
> in?), and then syzkaller will figure out itself how to send nasty IP
> packets through them with send/recv and such. There's a bit of surface
> here because sending packets provokes the aforementioned handshake,
> and also moves around the timer state machine. The receiver also needs
> to do some minimal parsing of the received packet to check
> "allowedips". So, good fodder for fuzzing.

Yes, there is this location to pre-create some net devices in right states:
https://github.com/google/syzkaller/blob/79b211f74b08737aeb4934c6ff69a263b3c38013/executor/common_linux.h#L668
(not in Go, but in C because eventually it will become part of C reproducers).
For example it creates vcan0 device and then syscall descriptions know
this name and use it.