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.