2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 "golang.org/x/crypto/poly1305"
29 "golang.org/x/crypto/salsa20"
30 "golang.org/x/crypto/xtea"
36 // S20BS is Salsa20's internal blocksize in bytes
39 // Maximal amount of bytes transfered with single key (4 GiB)
40 MaxBytesPerKey = 1 << 32
51 Key *[KeySize]byte // encryption key
52 NonceOur uint64 // nonce for our messages
53 NonceRecv uint64 // latest received nonce from remote peer
54 NonceCipher *xtea.Cipher // nonce cipher
58 tag *[poly1305.TagSize]byte
59 keyAuth *[KeySize]byte
66 func (p *Peer) String() string {
67 return p.Id.String() + ":" + p.Addr.String()
70 // Zero peer's memory state
71 func (p *Peer) Zero() {
74 sliceZero(p.keyAuth[:])
81 HeartbeatMark = []byte("\x00\x00\x00HEARTBEAT")
82 Emptiness = make([]byte, KeySize)
83 taps = make(map[string]*TAP)
84 heartbeatPeriod *time.Duration
87 func heartbeatPeriodGet() time.Duration {
88 if heartbeatPeriod == nil {
89 period := time.Second * time.Duration(Timeout/4)
90 heartbeatPeriod = &period
92 return *heartbeatPeriod
95 // Create TAP listening goroutine.
96 // This function takes required TAP interface name, opens it and allocates
97 // a buffer where all frame data will be written, channel where information
98 // about number of read bytes is sent to, synchronization channel (external
99 // processes tell that read buffer can be used again) and possible channel
101 func TAPListen(ifaceName string) (*TAP, chan []byte, chan struct{}, chan struct{}, error) {
104 tap, exists := taps[ifaceName]
106 tap, err = NewTAP(ifaceName)
108 return nil, nil, nil, nil, err
110 taps[ifaceName] = tap
112 sink := make(chan []byte)
113 sinkReady := make(chan struct{})
114 sinkTerminate := make(chan struct{})
115 sinkSkip := make(chan struct{})
118 heartbeat := time.Tick(heartbeatPeriodGet())
123 case <-sinkTerminate:
126 go func() { sink <- make([]byte, 0) }()
130 tap.ready <- struct{}{}
136 go func() { sink <- make([]byte, 0) }()
137 goto HeartbeatCatched
138 case <-sinkTerminate:
140 case pkt = <-tap.sink:
149 if exists && tap.synced {
150 sinkSkip <- struct{}{}
152 sinkReady <- struct{}{}
154 return tap, sink, sinkReady, sinkTerminate, nil
157 // Create UDP listening goroutine.
158 // This function takes already listening UDP socket and a buffer where
159 // all UDP packet data will be saved, channel where information about
160 // remote address and number of written bytes are stored, and a channel
161 // used to tell that buffer is ready to be overwritten.
162 func ConnListen(conn *net.UDPConn) (chan *UDPPkt, []byte, chan struct{}) {
163 buf := make([]byte, MTU)
164 sink := make(chan *UDPPkt)
165 sinkReady := make(chan struct{})
166 go func(conn *net.UDPConn) {
168 var addr *net.UDPAddr
172 conn.SetReadDeadline(time.Now().Add(time.Second))
173 n, addr, err = conn.ReadFromUDP(buf)
175 // This is needed for ticking the timeouts counter outside
179 sink <- &UDPPkt{addr, n}
182 sinkReady <- struct{}{}
183 return sink, buf, sinkReady
186 func newNonceCipher(key *[KeySize]byte) *xtea.Cipher {
187 nonceKey := make([]byte, 16)
188 salsa20.XORKeyStream(nonceKey, make([]byte, KeySize), make([]byte, xtea.BlockSize), key)
189 ciph, err := xtea.NewCipher(nonceKey)
196 func newPeer(addr *net.UDPAddr, id PeerId, nonce int, key *[KeySize]byte) *Peer {
199 LastPing: time.Now(),
201 NonceOur: uint64(Noncediff + nonce),
202 NonceRecv: uint64(Noncediff + 0),
204 NonceCipher: newNonceCipher(key),
206 buf: make([]byte, MTU+S20BS),
207 tag: new([poly1305.TagSize]byte),
208 keyAuth: new([KeySize]byte),
209 nonce: make([]byte, NonceSize),
214 // Process incoming UDP packet.
215 // udpPkt is received data, related to the peer tap interface and
216 // ConnListen'es synchronization channel used to tell him that he is
217 // free to receive new packets. Authenticated and decrypted packets
218 // will be written to the interface immediately (except heartbeat ones).
219 func (p *Peer) UDPProcess(udpPkt []byte, tap *TAP, ready chan struct{}) bool {
221 copy(p.buf[:KeySize], Emptiness)
222 copy(p.tag[:], udpPkt[size-poly1305.TagSize:])
223 copy(p.buf[S20BS:], udpPkt[NonceSize:size-poly1305.TagSize])
224 salsa20.XORKeyStream(
225 p.buf[:S20BS+size-poly1305.TagSize],
226 p.buf[:S20BS+size-poly1305.TagSize],
230 copy(p.keyAuth[:], p.buf[:KeySize])
231 if !poly1305.Verify(p.tag, udpPkt[:size-poly1305.TagSize], p.keyAuth) {
235 p.NonceCipher.Decrypt(p.buf, udpPkt[:NonceSize])
236 p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize])
237 if int(p.NonceRecv)-Noncediff >= 0 && int(p.nonceRecv) < int(p.NonceRecv)-Noncediff {
242 p.LastPing = time.Now()
243 p.NonceRecv = p.nonceRecv
244 p.frame = p.buf[S20BS : S20BS+size-NonceSize-poly1305.TagSize]
245 p.Bytes += len(p.frame)
246 if subtle.ConstantTimeCompare(p.frame[:HeartbeatSize], HeartbeatMark) == 1 {
253 // Process incoming Ethernet packet.
254 // ethPkt is received data, conn is our outgoing connection.
255 // ready channel is TAPListen's synchronization channel used to tell him
256 // that he is free to receive new packets. Encrypted and authenticated
257 // packets will be sent to remote Peer side immediately.
258 func (p *Peer) EthProcess(ethPkt []byte, conn *net.UDPConn, ready chan struct{}) {
261 // If this heartbeat is necessary
262 if size == 0 && !p.LastSent.Add(heartbeatPeriodGet()).Before(now) {
265 copy(p.buf[:KeySize], Emptiness)
267 copy(p.buf[S20BS:], ethPkt)
270 copy(p.buf[S20BS:], HeartbeatMark)
274 p.NonceOur = p.NonceOur + 2
275 copy(p.nonce, Emptiness)
276 binary.PutUvarint(p.nonce, p.NonceOur)
277 p.NonceCipher.Encrypt(p.nonce, p.nonce)
279 salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
280 copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
281 copy(p.keyAuth[:], p.buf[:KeySize])
282 p.frame = p.buf[S20BS-NonceSize : S20BS+size]
283 poly1305.Sum(p.tag, p.frame, p.keyAuth)
285 p.Bytes += len(p.frame)
287 if _, err := conn.WriteTo(append(p.frame, p.tag[:]...), p.Addr); err != nil {
288 log.Println("Error sending UDP", err)