From: Sergey Matveev Date: Wed, 10 Apr 2024 22:26:02 +0000 (+0300) Subject: Verify MACs on server side X-Git-Tag: v1.0.0~17 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=5e583f7c410db9e4c4cc3e7aac74b97fc919ca5365a6d4ee41c8a0d102fd8112;p=vors.git Verify MACs on server side --- diff --git a/cmd/client/main.go b/cmd/client/main.go index 87d77fc..bad619f 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -44,8 +44,6 @@ import ( "gopkg.in/hraban/opus.v2" ) -const TagLen = 8 - type Stream struct { name string ctr uint32 @@ -314,15 +312,18 @@ func main() { ciph.XORKeyStream(macKey[:], macKey[:]) ciph.SetCounter(1) mac = poly1305.New(&macKey) - if _, err = mac.Write(buf[4 : len(buf)-TagLen]); err != nil { + if _, err = mac.Write(buf[4 : len(buf)-vors.TagLen]); err != nil { log.Fatal(err) } mac.Sum(tag[:0]) - if subtle.ConstantTimeCompare(tag[:TagLen], buf[len(buf)-TagLen:]) != 1 { + if subtle.ConstantTimeCompare( + tag[:vors.TagLen], + buf[len(buf)-vors.TagLen:], + ) != 1 { log.Println("decrypt:", stream.name, "tag differs") continue } - pkt = buf[4 : len(buf)-TagLen] + pkt = buf[4 : len(buf)-vors.TagLen] ciph.XORKeyStream(pkt, pkt) ctr = binary.BigEndian.Uint32(nonce[len(nonce)-4:]) @@ -430,7 +431,7 @@ func main() { log.Println("wrong addr:", from) continue } - if n <= 1+4+poly1305.TagSize { + if n <= 4+vors.TagLen { log.Println("too small:", n) continue } @@ -513,8 +514,8 @@ func main() { log.Fatal(err) } mac.Sum(tag[:0]) - copy(buf[4+n:], tag[:TagLen]) - pkt = buf[:4+n+TagLen] + copy(buf[4+n:], tag[:vors.TagLen]) + pkt = buf[:4+n+vors.TagLen] OurStats.pkts++ OurStats.bytes += uint64(len(pkt)) diff --git a/cmd/server/main.go b/cmd/server/main.go index 52b34c3..76c479c 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -18,6 +18,7 @@ package main import ( "bufio" "crypto/rand" + "crypto/subtle" "crypto/tls" "encoding/hex" "flag" @@ -37,7 +38,9 @@ import ( "github.com/jroimartin/gocui" vors "go.stargrave.org/vors/internal" "golang.org/x/crypto/blake2s" + "golang.org/x/crypto/chacha20" "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/poly1305" ) var ( @@ -312,6 +315,11 @@ func main() { var err error var sid byte var peer *Peer + var ciph *chacha20.Cipher + var macKey [32]byte + var mac *poly1305.MAC + tag := make([]byte, poly1305.TagSize) + nonce := make([]byte, 12) for { n, from, err = lnUDP.ReadFromUDP(buf) if err != nil { @@ -335,6 +343,33 @@ func main() { if n == 1 { continue } + if n <= 4+vors.TagLen { + slog.Info("too small:", "peer", peer.name, "len", n) + continue + } + + copy(nonce[len(nonce)-4:], buf) + ciph, err = chacha20.NewUnauthenticatedCipher(peer.key, nonce) + if err != nil { + log.Fatal(err) + } + clear(macKey[:]) + ciph.XORKeyStream(macKey[:], macKey[:]) + ciph.SetCounter(1) + mac = poly1305.New(&macKey) + if _, err = mac.Write(buf[4 : n-vors.TagLen]); err != nil { + log.Fatal(err) + } + mac.Sum(tag[:0]) + if subtle.ConstantTimeCompare( + tag[:vors.TagLen], + buf[n-vors.TagLen:n], + ) != 1 { + log.Println("decrypt:", peer.name, "tag differs") + slog.Info("MAC failed:", "peer", peer.name, "len", n) + continue + } + peer.stats.last = time.Now() for _, p := range Peers { if p.sid == sid { diff --git a/doc/index.texi b/doc/index.texi index f077115..8dfdb6d 100644 --- a/doc/index.texi +++ b/doc/index.texi @@ -53,9 +53,7 @@ appropriate and satisfiable as fast and secure encryption solution. @end itemize -TODO: server should verify symmetric authentication tags on incoming -traffic, before copying it to everyone. Look at latest Opus'es neural -network abilities. +TODO: Look at latest Opus'es neural network abilities. @include install.texi @include usage.texi diff --git a/internal/var.go b/internal/var.go index df03cd5..fbc5544 100644 --- a/internal/var.go +++ b/internal/var.go @@ -10,6 +10,7 @@ const ( CN = "vors" MaxLost = 32 + TagLen = 8 CmdPing = "PING" CmdPong = "PONG"