]> Cypherpunks.ru repositories - govpn.git/blob - transport.go
Split long line
[govpn.git] / transport.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2015 Sergey Matveev <stargrave@stargrave.org>
4
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.
9
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.
14
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/>.
17 */
18
19 package govpn
20
21 import (
22         "crypto/subtle"
23         "encoding/binary"
24         "log"
25         "net"
26         "time"
27
28         "golang.org/x/crypto/poly1305"
29         "golang.org/x/crypto/salsa20"
30         "golang.org/x/crypto/xtea"
31 )
32
33 const (
34         NonceSize = 8
35         KeySize   = 32
36         // S20BS is Salsa20's internal blocksize in bytes
37         S20BS         = 64
38         HeartbeatSize = 12
39         // Maximal amount of bytes transfered with single key (4 GiB)
40         MaxBytesPerKey int64 = 1 << 32
41 )
42
43 type UDPPkt struct {
44         Addr *net.UDPAddr
45         Size int
46 }
47
48 type Peer struct {
49         Addr        *net.UDPAddr
50         Id          PeerId
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
55         LastPing    time.Time
56         LastSent    time.Time
57         buf         []byte
58         tag         *[poly1305.TagSize]byte
59         keyAuth     *[KeySize]byte
60         nonceRecv   uint64
61         Bytes       int64
62         frame       []byte
63         nonce       []byte
64 }
65
66 func (p *Peer) String() string {
67         return p.Id.String() + ":" + p.Addr.String()
68 }
69
70 // Zero peer's memory state
71 func (p *Peer) Zero() {
72         sliceZero(p.Key[:])
73         sliceZero(p.tag[:])
74         sliceZero(p.keyAuth[:])
75         sliceZero(p.buf)
76         sliceZero(p.frame)
77         sliceZero(p.nonce)
78 }
79
80 var (
81         HeartbeatMark   = []byte("\x00\x00\x00HEARTBEAT")
82         Emptiness       = make([]byte, KeySize)
83         taps            = make(map[string]*TAP)
84         heartbeatPeriod *time.Duration
85 )
86
87 func heartbeatPeriodGet() time.Duration {
88         if heartbeatPeriod == nil {
89                 period := time.Second * time.Duration(Timeout/4)
90                 heartbeatPeriod = &period
91         }
92         return *heartbeatPeriod
93 }
94
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
100 // opening error.
101 func TAPListen(ifaceName string) (*TAP, chan []byte, chan struct{}, chan struct{}, error) {
102         var tap *TAP
103         var err error
104         tap, exists := taps[ifaceName]
105         if !exists {
106                 tap, err = NewTAP(ifaceName)
107                 if err != nil {
108                         return nil, nil, nil, nil, err
109                 }
110                 taps[ifaceName] = tap
111         }
112         sink := make(chan []byte)
113         sinkReady := make(chan struct{})
114         sinkTerminate := make(chan struct{})
115         sinkSkip := make(chan struct{})
116
117         go func() {
118                 heartbeat := time.Tick(heartbeatPeriodGet())
119                 var pkt []byte
120         ListenCycle:
121                 for {
122                         select {
123                         case <-sinkTerminate:
124                                 break ListenCycle
125                         case <-heartbeat:
126                                 go func() { sink <- make([]byte, 0) }()
127                                 continue
128                         case <-sinkSkip:
129                         case <-sinkReady:
130                                 tap.ready <- struct{}{}
131                                 tap.synced = true
132                         }
133                 HeartbeatCatched:
134                         select {
135                         case <-heartbeat:
136                                 go func() { sink <- make([]byte, 0) }()
137                                 goto HeartbeatCatched
138                         case <-sinkTerminate:
139                                 break ListenCycle
140                         case pkt = <-tap.sink:
141                                 tap.synced = false
142                                 sink <- pkt
143                         }
144                 }
145                 close(sink)
146                 close(sinkReady)
147                 close(sinkTerminate)
148         }()
149         if exists && tap.synced {
150                 sinkSkip <- struct{}{}
151         } else {
152                 sinkReady <- struct{}{}
153         }
154         return tap, sink, sinkReady, sinkTerminate, nil
155 }
156
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) {
167                 var n int
168                 var addr *net.UDPAddr
169                 var err error
170                 for {
171                         <-sinkReady
172                         conn.SetReadDeadline(time.Now().Add(time.Second))
173                         n, addr, err = conn.ReadFromUDP(buf)
174                         if err != nil {
175                                 // This is needed for ticking the timeouts counter outside
176                                 sink <- nil
177                                 continue
178                         }
179                         sink <- &UDPPkt{addr, n}
180                 }
181         }(conn)
182         sinkReady <- struct{}{}
183         return sink, buf, sinkReady
184 }
185
186 func newNonceCipher(key *[KeySize]byte) *xtea.Cipher {
187         nonceKey := make([]byte, 16)
188         salsa20.XORKeyStream(
189                 nonceKey,
190                 make([]byte, KeySize),
191                 make([]byte, xtea.BlockSize),
192                 key,
193         )
194         ciph, err := xtea.NewCipher(nonceKey)
195         if err != nil {
196                 panic(err)
197         }
198         return ciph
199 }
200
201 func newPeer(addr *net.UDPAddr, id PeerId, nonce int, key *[KeySize]byte) *Peer {
202         peer := Peer{
203                 Addr:        addr,
204                 LastPing:    time.Now(),
205                 Id:          id,
206                 NonceOur:    uint64(Noncediff + nonce),
207                 NonceRecv:   uint64(Noncediff + 0),
208                 Key:         key,
209                 NonceCipher: newNonceCipher(key),
210                 Bytes:       0,
211                 buf:         make([]byte, MTU+S20BS),
212                 tag:         new([poly1305.TagSize]byte),
213                 keyAuth:     new([KeySize]byte),
214                 nonce:       make([]byte, NonceSize),
215         }
216         return &peer
217 }
218
219 // Process incoming UDP packet.
220 // udpPkt is received data, related to the peer tap interface and
221 // ConnListen'es synchronization channel used to tell him that he is
222 // free to receive new packets. Authenticated and decrypted packets
223 // will be written to the interface immediately (except heartbeat ones).
224 func (p *Peer) UDPProcess(udpPkt []byte, tap *TAP, ready chan struct{}) bool {
225         size := len(udpPkt)
226         copy(p.buf[:KeySize], Emptiness)
227         copy(p.tag[:], udpPkt[size-poly1305.TagSize:])
228         copy(p.buf[S20BS:], udpPkt[NonceSize:size-poly1305.TagSize])
229         salsa20.XORKeyStream(
230                 p.buf[:S20BS+size-poly1305.TagSize],
231                 p.buf[:S20BS+size-poly1305.TagSize],
232                 udpPkt[:NonceSize],
233                 p.Key,
234         )
235         copy(p.keyAuth[:], p.buf[:KeySize])
236         if !poly1305.Verify(p.tag, udpPkt[:size-poly1305.TagSize], p.keyAuth) {
237                 ready <- struct{}{}
238                 return false
239         }
240         p.NonceCipher.Decrypt(p.buf, udpPkt[:NonceSize])
241         p.nonceRecv, _ = binary.Uvarint(p.buf[:NonceSize])
242         if int(p.NonceRecv)-Noncediff >= 0 && int(p.nonceRecv) < int(p.NonceRecv)-Noncediff {
243                 ready <- struct{}{}
244                 return false
245         }
246         ready <- struct{}{}
247         p.LastPing = time.Now()
248         p.NonceRecv = p.nonceRecv
249         p.frame = p.buf[S20BS : S20BS+size-NonceSize-poly1305.TagSize]
250         p.Bytes += int64(len(p.frame))
251         if subtle.ConstantTimeCompare(p.frame[:HeartbeatSize], HeartbeatMark) == 1 {
252                 return true
253         }
254         tap.Write(p.frame)
255         return true
256 }
257
258 // Process incoming Ethernet packet.
259 // ethPkt is received data, conn is our outgoing connection.
260 // ready channel is TAPListen's synchronization channel used to tell him
261 // that he is free to receive new packets. Encrypted and authenticated
262 // packets will be sent to remote Peer side immediately.
263 func (p *Peer) EthProcess(ethPkt []byte, conn *net.UDPConn, ready chan struct{}) {
264         now := time.Now()
265         size := len(ethPkt)
266         // If this heartbeat is necessary
267         if size == 0 && !p.LastSent.Add(heartbeatPeriodGet()).Before(now) {
268                 return
269         }
270         copy(p.buf[:KeySize], Emptiness)
271         if size > 0 {
272                 copy(p.buf[S20BS:], ethPkt)
273                 ready <- struct{}{}
274         } else {
275                 copy(p.buf[S20BS:], HeartbeatMark)
276                 size = HeartbeatSize
277         }
278
279         p.NonceOur = p.NonceOur + 2
280         copy(p.nonce, Emptiness)
281         binary.PutUvarint(p.nonce, p.NonceOur)
282         p.NonceCipher.Encrypt(p.nonce, p.nonce)
283
284         salsa20.XORKeyStream(p.buf, p.buf, p.nonce, p.Key)
285         copy(p.buf[S20BS-NonceSize:S20BS], p.nonce)
286         copy(p.keyAuth[:], p.buf[:KeySize])
287         p.frame = p.buf[S20BS-NonceSize : S20BS+size]
288         poly1305.Sum(p.tag, p.frame, p.keyAuth)
289
290         p.Bytes += int64(len(p.frame))
291         p.LastSent = now
292         if _, err := conn.WriteTo(append(p.frame, p.tag[:]...), p.Addr); err != nil {
293                 log.Println("Error sending UDP", err)
294         }
295 }