/*
govpn -- simple secure virtual private network daemon
-Copyright (C) 2014 Sergey Matveev <stargrave@stargrave.org>
+Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
"golang.org/x/crypto/poly1305"
"golang.org/x/crypto/salsa20"
+ "golang.org/x/crypto/xtea"
)
var (
}
type Peer struct {
- addr *net.UDPAddr
- key *[KeySize]byte // encryption key
- nonceOur uint64 // nonce for our messages
- nonceRecv uint64 // latest received nonce from remote peer
+ addr *net.UDPAddr
+ key *[KeySize]byte // encryption key
+ nonceOur uint64 // nonce for our messages
+ nonceRecv uint64 // latest received nonce from remote peer
+ nonceCipher *xtea.Cipher // nonce cipher
}
type UDPPkt struct {
timeout := *timeoutP
verbose := *verboseP
noncediff := uint64(*nonceDiff)
+ var err error
log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
// Key decoding
ethSink := make(chan int)
ethSinkReady := make(chan bool)
go func() {
+ var n int
+ var err error
for {
<-ethSinkReady
- n, err := iface.Read(ethBuf)
+ n, err = iface.Read(ethBuf)
if err != nil {
panic(err)
}
udpSink := make(chan *UDPPkt)
udpSinkReady := make(chan bool)
go func(conn *net.UDPConn) {
+ var n int
+ var addr *net.UDPAddr
+ var err error
for {
<-udpSinkReady
conn.SetReadDeadline(time.Now().Add(time.Second))
- n, addr, err := conn.ReadFromUDP(udpBuf)
+ n, addr, err = conn.ReadFromUDP(udpBuf)
if err != nil {
if verbose {
fmt.Print("B")
var udpPktData []byte
var ethPktSize int
var frame []byte
+ var dataToSend []byte
var addr string
var peer *Peer
var p *Peer
+ var nonceRecv uint64
timeouts := 0
bytes := 0
udpSinkReady <- true
continue
}
- nonceRecv, _ := binary.Uvarint(udpPktData[:8])
- if nonceRecv < peer.nonceRecv-noncediff {
- fmt.Print("R")
- udpSinkReady <- true
- continue
- }
copy(buf[:KeySize], emptyKey)
copy(tag[:], udpPktData[udpPkt.size-poly1305.TagSize:])
copy(buf[S20BS:], udpPktData[NonceSize:udpPkt.size-poly1305.TagSize])
fmt.Print("T")
continue
}
+ peer.nonceCipher.Decrypt(buf, udpPktData[:NonceSize])
+ nonceRecv, _ = binary.Uvarint(buf[:NonceSize])
+ if nonceRecv < peer.nonceRecv-noncediff {
+ fmt.Print("R")
+ udpSinkReady <- true
+ continue
+ }
udpSinkReady <- true
peer.nonceRecv = nonceRecv
timeouts = 0
if string(frame[0:HeartBeatSize]) == HeartBeatMark {
continue
}
- if _, err := iface.Write(frame); err != nil {
+ if _, err = iface.Write(frame); err != nil {
log.Println("Error writing to iface: ", err)
}
if verbose {
ethSinkReady <- true
continue
}
+
peer.nonceOur = peer.nonceOur + 2
+ for i := 0; i < NonceSize; i++ {
+ nonce[i] = '\x00'
+ }
binary.PutUvarint(nonce, peer.nonceOur)
+ peer.nonceCipher.Encrypt(nonce, nonce)
+
copy(buf[:KeySize], emptyKey)
if ethPktSize > -1 {
copy(buf[S20BS:], ethBuf[:ethPktSize])
salsa20.XORKeyStream(buf, buf, nonce, peer.key)
copy(buf[S20BS-NonceSize:S20BS], nonce)
copy(keyAuth[:], buf[:KeySize])
- dataToSend := buf[S20BS-NonceSize : S20BS+ethPktSize]
+ dataToSend = buf[S20BS-NonceSize : S20BS+ethPktSize]
poly1305.Sum(tag, dataToSend, keyAuth)
bytes += len(dataToSend)
- if _, err := conn.WriteTo(append(dataToSend, tag[:]...), peer.addr); err != nil {
+ if _, err = conn.WriteTo(append(dataToSend, tag[:]...), peer.addr); err != nil {
log.Println("Error sending UDP", err)
}
if verbose {