]> Sergey Matveev's repositories - vors.git/blobdiff - cmd/server/main.go
Verify MACs on server side
[vors.git] / cmd / server / main.go
index 52b34c351855b4263b959a5e7428eca2a8c4409ba43842bd23519f20b0503a95..76c479c0d0dec0f048b1ff90ab705adfab55dfac8c42734605e387ae880ba61f 100644 (file)
@@ -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 {