]> Cypherpunks.ru repositories - govpn.git/commitdiff
Explicitly store payload size in each message
authorSergey Matveev <stargrave@stargrave.org>
Fri, 1 May 2015 14:59:46 +0000 (17:59 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Fri, 1 May 2015 16:52:05 +0000 (19:52 +0300)
Signed-off-by: Sergey Matveev <stargrave@stargrave.org>
doc/developer.texi
doc/transport.texi
tap.go
transport.go

index b257885b02858362b7ff9a4b72f2d9cddbe8701d..b218c35b0d612ff5b4944193db84b33928407336 100644 (file)
@@ -11,7 +11,7 @@
 @item Password authenticated key agreement
 DH-EKE powered by @url{http://cr.yp.to/ecdh.html, Curve25519}
 @item Packet overhead
-24 bytes per packet
+26 bytes per packet
 @item Handshake overhead
 4 UDP (2 from client, 2 from server) packets, 200 bytes total payload
 @end table
index d0cb75642564dbee51a693c1943fd9bbe9657840..b12a308469d54c840f6c23997c76ca877e3c9e6a 100644 (file)
@@ -2,8 +2,8 @@
 @section Transport protocol
 
 @verbatim
-ENCn(SERIAL) + ENC(KEY, ENCn(SERIAL), DATA) +
-    AUTH(ENCn(SERIAL) + ENC(KEY, ENCn(SERIAL), DATA))
+ENCn(SERIAL) + ENC(KEY, ENCn(SERIAL), DATA_SIZE+DATA) +
+    AUTH(ENCn(SERIAL) + ENC(KEY, ENCn(SERIAL), DATA_SIZE+DATA))
 @end verbatim
 
 All transport and handshake messages are indistinguishable from
@@ -24,6 +24,7 @@ Encrypted @code{SERIAL} is used as a nonce for @code{DATA} encryption:
 encryption key is different during each handshake, so (key, nonce) pair
 is always used only once. @code{ENC} is Salsa20 cipher, with established
 session @code{KEY} and encrypted @code{SERIAL} used as a nonce.
+@code{DATA_SIZE} is @emph{uint16} storing length of the @code{DATA}.
 
 @code{AUTH} is Poly1305 authentication function. First 256 bits of
 Salsa20 output are used as a one-time key for @code{AUTH}. Next 256 bits
diff --git a/tap.go b/tap.go
index 6b298f713861ec621183dd4f546d00f2fd7afe77..8a19df344530ef7e181a92ce4790c68b9ad2fe44 100644 (file)
--- a/tap.go
+++ b/tap.go
@@ -24,6 +24,10 @@ import (
        "golang.org/x/crypto/poly1305"
 )
 
+const (
+       EtherSize = 14
+)
+
 type TAP struct {
        Name   string
        dev    io.ReadWriter
@@ -33,8 +37,12 @@ type TAP struct {
        synced bool
 }
 
+func TAPMaxMTU() int {
+       return MTU - poly1305.TagSize - NonceSize - PktSizeSize - EtherSize
+}
+
 func NewTAP(ifaceName string) (*TAP, error) {
-       maxIfacePktSize := MTU - poly1305.TagSize - NonceSize
+       maxIfacePktSize := TAPMaxMTU() + EtherSize
        tapRaw, err := newTAPer(ifaceName)
        if err != nil {
                return nil, err
index 2638243311f17eed8bed6744d85a6ad8ee129eb7..4277628b3fb87ab1d9510152a83b31b129d6e946 100644 (file)
@@ -19,7 +19,6 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 package govpn
 
 import (
-       "crypto/subtle"
        "encoding/binary"
        "io"
        "log"
@@ -35,10 +34,11 @@ const (
        NonceSize = 8
        KeySize   = 32
        // S20BS is Salsa20's internal blocksize in bytes
-       S20BS         = 64
-       HeartbeatSize = 12
+       S20BS = 64
        // Maximal amount of bytes transfered with single key (4 GiB)
        MaxBytesPerKey int64 = 1 << 32
+       // Size of packet's size mark in bytes
+       PktSizeSize = 2
 )
 
 type UDPPkt struct {
@@ -61,6 +61,7 @@ type Peer struct {
        nonceRecv     uint64
        frame         []byte
        nonce         []byte
+       pktSize       uint64
        BytesIn       int64
        BytesOut      int64
        FramesIn      int
@@ -86,8 +87,7 @@ func (p *Peer) Zero() {
 }
 
 var (
-       HeartbeatMark   = []byte("\x00\x00\x00HEARTBEAT")
-       Emptiness       = make([]byte, KeySize)
+       Emptiness       = make([]byte, 1<<16)
        taps            = make(map[string]*TAP)
        heartbeatPeriod *time.Duration
 )
@@ -230,7 +230,7 @@ func newPeer(addr *net.UDPAddr, id PeerId, nonce int, key *[KeySize]byte) *Peer
 // will be written to the interface immediately (except heartbeat ones).
 func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) bool {
        size := len(udpPkt)
-       copy(p.buf[:KeySize], Emptiness)
+       copy(p.buf, Emptiness)
        copy(p.tag[:], udpPkt[size-poly1305.TagSize:])
        copy(p.buf[S20BS:], udpPkt[NonceSize:size-poly1305.TagSize])
        salsa20.XORKeyStream(
@@ -255,13 +255,14 @@ func (p *Peer) UDPProcess(udpPkt []byte, tap io.Writer, ready chan struct{}) boo
        ready <- struct{}{}
        p.LastPing = time.Now()
        p.NonceRecv = p.nonceRecv
-       p.frame = p.buf[S20BS : S20BS+size-NonceSize-poly1305.TagSize]
-       p.BytesIn += int64(len(p.frame))
-       p.FramesIn++
-       if subtle.ConstantTimeCompare(p.frame[:HeartbeatSize], HeartbeatMark) == 1 {
+       p.pktSize, _ = binary.Uvarint(p.buf[S20BS : S20BS+PktSizeSize])
+       if p.pktSize == 0 {
                p.HeartbeatRecv++
                return true
        }
+       p.frame = p.buf[S20BS+PktSizeSize : S20BS+PktSizeSize+p.pktSize]
+       p.BytesIn += int64(p.pktSize)
+       p.FramesIn++
        tap.Write(p.frame)
        return true
 }
@@ -282,14 +283,14 @@ func (p *Peer) EthProcess(ethPkt []byte, conn WriteToer, ready chan struct{}) {
        if size == 0 && !p.LastSent.Add(heartbeatPeriodGet()).Before(now) {
                return
        }
-       copy(p.buf[:KeySize], Emptiness)
+       copy(p.buf, Emptiness)
        if size > 0 {
-               copy(p.buf[S20BS:], ethPkt)
+               copy(p.buf[S20BS+PktSizeSize:], ethPkt)
                ready <- struct{}{}
+               binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(size))
+               p.BytesOut += int64(size)
        } else {
                p.HeartbeatSent++
-               copy(p.buf[S20BS:], HeartbeatMark)
-               size = HeartbeatSize
        }
 
        p.NonceOur = p.NonceOur + 2
@@ -300,10 +301,9 @@ func (p *Peer) EthProcess(ethPkt []byte, conn WriteToer, ready chan struct{}) {
        salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
        copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
        copy(p.keyAuth[:], p.buf[:KeySize])
-       p.frame = p.buf[S20BS-NonceSize : S20BS+size]
+       p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+size]
        poly1305.Sum(p.tag, p.frame, p.keyAuth)
 
-       p.BytesOut += int64(len(p.frame))
        p.FramesOut++
        p.LastSent = now
        if _, err := conn.WriteTo(append(p.frame, p.tag[:]...), p.Addr); err != nil {