]> Cypherpunks.ru repositories - govpn.git/blob - src/cypherpunks.ru/govpn/handshake.go
9c536b329371fe7a5a946229407285214dbd5e30
[govpn.git] / src / cypherpunks.ru / govpn / handshake.go
1 /*
2 GoVPN -- simple secure free software virtual private network daemon
3 Copyright (C) 2014-2016 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         "io"
25         "log"
26         "time"
27
28         "github.com/agl/ed25519"
29         "github.com/agl/ed25519/extra25519"
30         "github.com/dchest/blake2b"
31         "golang.org/x/crypto/curve25519"
32         "golang.org/x/crypto/salsa20"
33 )
34
35 const (
36         RSize = 8
37         SSize = 32
38 )
39
40 type Handshake struct {
41         addr     string
42         conn     io.Writer
43         LastPing time.Time
44         Conf     *PeerConf
45         dsaPubH  *[ed25519.PublicKeySize]byte
46         key      *[32]byte
47         rNonce   *[RSize]byte
48         dhPriv   *[32]byte    // own private DH key
49         rServer  *[RSize]byte // random string for authentication
50         rClient  *[RSize]byte
51         sServer  *[SSize]byte // secret string for main key calculation
52         sClient  *[SSize]byte
53 }
54
55 func keyFromSecrets(server, client []byte) *[SSize]byte {
56         k := new([SSize]byte)
57         for i := 0; i < SSize; i++ {
58                 k[i] = server[i] ^ client[i]
59         }
60         return k
61 }
62
63 // Zero handshake's memory state
64 func (h *Handshake) Zero() {
65         if h.rNonce != nil {
66                 SliceZero(h.rNonce[:])
67         }
68         if h.dhPriv != nil {
69                 SliceZero(h.dhPriv[:])
70         }
71         if h.key != nil {
72                 SliceZero(h.key[:])
73         }
74         if h.dsaPubH != nil {
75                 SliceZero(h.dsaPubH[:])
76         }
77         if h.rServer != nil {
78                 SliceZero(h.rServer[:])
79         }
80         if h.rClient != nil {
81                 SliceZero(h.rClient[:])
82         }
83         if h.sServer != nil {
84                 SliceZero(h.sServer[:])
85         }
86         if h.sClient != nil {
87                 SliceZero(h.sClient[:])
88         }
89 }
90
91 func (h *Handshake) rNonceNext(count uint64) []byte {
92         nonce := make([]byte, RSize)
93         nonceCurrent, _ := binary.Uvarint(h.rNonce[:])
94         binary.PutUvarint(nonce, nonceCurrent+count)
95         return nonce
96 }
97
98 func dhKeypairGen() (*[32]byte, *[32]byte) {
99         priv := new([32]byte)
100         pub := new([32]byte)
101         repr := new([32]byte)
102         reprFound := false
103         for !reprFound {
104                 if _, err := io.ReadFull(Rand, priv[:]); err != nil {
105                         log.Fatalln("Error reading random for DH private key:", err)
106                 }
107                 reprFound = extra25519.ScalarBaseMult(pub, repr, priv)
108         }
109         return priv, repr
110 }
111
112 func dhKeyGen(priv, pub *[32]byte) *[32]byte {
113         key := new([32]byte)
114         curve25519.ScalarMult(key, priv, pub)
115         hashed := blake2b.Sum256(key[:])
116         return &hashed
117 }
118
119 // Create new handshake state.
120 func NewHandshake(addr string, conn io.Writer, conf *PeerConf) *Handshake {
121         state := Handshake{
122                 addr:     addr,
123                 conn:     conn,
124                 LastPing: time.Now(),
125                 Conf:     conf,
126         }
127         state.dsaPubH = new([ed25519.PublicKeySize]byte)
128         copy(state.dsaPubH[:], state.Conf.Verifier.Pub[:])
129         hashed := blake2b.Sum256(state.dsaPubH[:])
130         state.dsaPubH = &hashed
131         return &state
132 }
133
134 // Generate ID tag from client identification and data.
135 func idTag(id *PeerId, timeSync int, data []byte) []byte {
136         enc := make([]byte, 8)
137         copy(enc, data)
138         AddTimeSync(timeSync, enc)
139         mac := blake2b.NewMAC(8, id[:])
140         mac.Write(enc)
141         mac.Sum(enc[:0])
142         return enc
143 }
144
145 // Start handshake's procedure from the client. It is the entry point
146 // for starting the handshake procedure. // First handshake packet
147 // will be sent immediately.
148 func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
149         state := NewHandshake(addr, conn, conf)
150         var dhPubRepr *[32]byte
151         state.dhPriv, dhPubRepr = dhKeypairGen()
152
153         state.rNonce = new([RSize]byte)
154         if _, err := io.ReadFull(Rand, state.rNonce[:]); err != nil {
155                 log.Fatalln("Error reading random for nonce:", err)
156         }
157         var enc []byte
158         if conf.Noise {
159                 enc = make([]byte, conf.MTU-8-RSize)
160         } else {
161                 enc = make([]byte, 32)
162         }
163         copy(enc, dhPubRepr[:])
164         if conf.Encless {
165                 var err error
166                 enc, err = EnclessEncode(state.dsaPubH, state.rNonce[:], enc)
167                 if err != err {
168                         panic(err)
169                 }
170         } else {
171                 salsa20.XORKeyStream(enc, enc, state.rNonce[:], state.dsaPubH)
172         }
173         data := append(state.rNonce[:], enc...)
174         data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[:])...)
175         state.conn.Write(data)
176         return state
177 }
178
179 // Process handshake message on the server side.
180 // This function is intended to be called on server's side.
181 // If this is the final handshake message, then new Peer object
182 // will be created and used as a transport. If no mutually
183 // authenticated Peer is ready, then return nil.
184 func (h *Handshake) Server(data []byte) *Peer {
185         // R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag
186         if h.rNonce == nil && ((!h.Conf.Encless && len(data) >= 48) ||
187                 (h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
188                 h.rNonce = new([RSize]byte)
189                 copy(h.rNonce[:], data[:RSize])
190
191                 // Decrypt remote public key
192                 cDHRepr := new([32]byte)
193                 if h.Conf.Encless {
194                         out, err := EnclessDecode(
195                                 h.dsaPubH,
196                                 h.rNonce[:],
197                                 data[RSize:len(data)-8],
198                         )
199                         if err != nil {
200                                 log.Println("Unable to decode packet from", h.addr, err)
201                                 return nil
202                         }
203                         copy(cDHRepr[:], out)
204                 } else {
205                         salsa20.XORKeyStream(cDHRepr[:], data[RSize:RSize+32], h.rNonce[:], h.dsaPubH)
206                 }
207
208                 // Generate DH keypair
209                 var dhPubRepr *[32]byte
210                 h.dhPriv, dhPubRepr = dhKeypairGen()
211
212                 // Compute shared key
213                 cDH := new([32]byte)
214                 extra25519.RepresentativeToPublicKey(cDH, cDHRepr)
215                 h.key = dhKeyGen(h.dhPriv, cDH)
216
217                 var encPub []byte
218                 var err error
219                 if h.Conf.Encless {
220                         encPub = make([]byte, h.Conf.MTU)
221                         copy(encPub, dhPubRepr[:])
222                         encPub, err = EnclessEncode(h.dsaPubH, h.rNonceNext(1), encPub)
223                         if err != nil {
224                                 panic(err)
225                         }
226                 } else {
227                         encPub = make([]byte, 32)
228                         salsa20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)
229                 }
230
231                 // Generate R* and encrypt them
232                 h.rServer = new([RSize]byte)
233                 if _, err = io.ReadFull(Rand, h.rServer[:]); err != nil {
234                         log.Fatalln("Error reading random for R:", err)
235                 }
236                 h.sServer = new([SSize]byte)
237                 if _, err = io.ReadFull(Rand, h.sServer[:]); err != nil {
238                         log.Fatalln("Error reading random for S:", err)
239                 }
240                 var encRs []byte
241                 if h.Conf.Noise && !h.Conf.Encless {
242                         encRs = make([]byte, h.Conf.MTU-len(encPub)-8)
243                 } else if h.Conf.Encless {
244                         encRs = make([]byte, h.Conf.MTU-8)
245                 } else {
246                         encRs = make([]byte, RSize+SSize)
247                 }
248                 copy(encRs, append(h.rServer[:], h.sServer[:]...))
249                 if h.Conf.Encless {
250                         encRs, err = EnclessEncode(h.key, h.rNonce[:], encRs)
251                         if err != nil {
252                                 panic(err)
253                         }
254                 } else {
255                         salsa20.XORKeyStream(encRs, encRs, h.rNonce[:], h.key)
256                 }
257
258                 // Send that to client
259                 h.conn.Write(append(encPub, append(
260                         encRs, idTag(h.Conf.Id, h.Conf.TimeSync, encPub)...,
261                 )...))
262                 h.LastPing = time.Now()
263         } else
264         // ENC(K, R+1, RS + RC + SC + Sign(DSAPriv, K)) + IDtag
265         if h.rClient == nil && ((!h.Conf.Encless && len(data) >= 120) ||
266                 (h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
267                 var dec []byte
268                 var err error
269                 if h.Conf.Encless {
270                         dec, err = EnclessDecode(
271                                 h.key,
272                                 h.rNonceNext(1),
273                                 data[:len(data)-8],
274                         )
275                         if err != nil {
276                                 log.Println("Unable to decode packet from", h.addr, err)
277                                 return nil
278                         }
279                         dec = dec[:RSize+RSize+SSize+ed25519.SignatureSize]
280                 } else {
281                         dec = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
282                         salsa20.XORKeyStream(
283                                 dec,
284                                 data[:RSize+RSize+SSize+ed25519.SignatureSize],
285                                 h.rNonceNext(1),
286                                 h.key,
287                         )
288                 }
289                 if subtle.ConstantTimeCompare(dec[:RSize], h.rServer[:]) != 1 {
290                         log.Println("Invalid server's random number with", h.addr)
291                         return nil
292                 }
293                 sign := new([ed25519.SignatureSize]byte)
294                 copy(sign[:], dec[RSize+RSize+SSize:])
295                 if !ed25519.Verify(h.Conf.Verifier.Pub, h.key[:], sign) {
296                         log.Println("Invalid signature from", h.addr)
297                         return nil
298                 }
299
300                 // Send final answer to client
301                 var enc []byte
302                 if h.Conf.Noise {
303                         enc = make([]byte, h.Conf.MTU-8)
304                 } else {
305                         enc = make([]byte, RSize)
306                 }
307                 copy(enc, dec[RSize:RSize+RSize])
308                 if h.Conf.Encless {
309                         enc, err = EnclessEncode(h.key, h.rNonceNext(2), enc)
310                         if err != nil {
311                                 panic(err)
312                         }
313                 } else {
314                         salsa20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
315                 }
316                 h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
317
318                 // Switch peer
319                 peer := newPeer(
320                         false,
321                         h.addr,
322                         h.conn,
323                         h.Conf,
324                         keyFromSecrets(h.sServer[:], dec[RSize+RSize:RSize+RSize+SSize]))
325                 h.LastPing = time.Now()
326                 return peer
327         } else {
328                 log.Println("Invalid handshake message from", h.addr)
329         }
330         return nil
331 }
332
333 // Process handshake message on the client side.
334 // This function is intended to be called on client's side.
335 // If this is the final handshake message, then new Peer object
336 // will be created and used as a transport. If no mutually
337 // authenticated Peer is ready, then return nil.
338 func (h *Handshake) Client(data []byte) *Peer {
339         // ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag
340         if h.rServer == nil && h.key == nil &&
341                 ((!h.Conf.Encless && len(data) >= 80) ||
342                         (h.Conf.Encless && len(data) == 2*(EnclessEnlargeSize+h.Conf.MTU))) {
343                 // Decrypt remote public key
344                 sDHRepr := new([32]byte)
345                 var tmp []byte
346                 var err error
347                 if h.Conf.Encless {
348                         tmp, err = EnclessDecode(
349                                 h.dsaPubH,
350                                 h.rNonceNext(1),
351                                 data[:len(data)/2],
352                         )
353                         if err != nil {
354                                 log.Println("Unable to decode packet from", h.addr, err)
355                                 return nil
356                         }
357                         copy(sDHRepr[:], tmp[:32])
358                 } else {
359                         salsa20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH)
360                 }
361
362                 // Compute shared key
363                 sDH := new([32]byte)
364                 extra25519.RepresentativeToPublicKey(sDH, sDHRepr)
365                 h.key = dhKeyGen(h.dhPriv, sDH)
366
367                 // Decrypt Rs
368                 h.rServer = new([RSize]byte)
369                 h.sServer = new([SSize]byte)
370                 if h.Conf.Encless {
371                         tmp, err = EnclessDecode(
372                                 h.key,
373                                 h.rNonce[:],
374                                 data[len(data)/2:len(data)-8],
375                         )
376                         if err != nil {
377                                 log.Println("Unable to decode packet from", h.addr, err)
378                                 return nil
379                         }
380                         copy(h.rServer[:], tmp[:RSize])
381                         copy(h.sServer[:], tmp[RSize:RSize+SSize])
382                 } else {
383                         decRs := make([]byte, RSize+SSize)
384                         salsa20.XORKeyStream(decRs, data[SSize:SSize+RSize+SSize], h.rNonce[:], h.key)
385                         copy(h.rServer[:], decRs[:RSize])
386                         copy(h.sServer[:], decRs[RSize:])
387                 }
388
389                 // Generate R* and signature and encrypt them
390                 h.rClient = new([RSize]byte)
391                 if _, err = io.ReadFull(Rand, h.rClient[:]); err != nil {
392                         log.Fatalln("Error reading random for R:", err)
393                 }
394                 h.sClient = new([SSize]byte)
395                 if _, err = io.ReadFull(Rand, h.sClient[:]); err != nil {
396                         log.Fatalln("Error reading random for S:", err)
397                 }
398                 sign := ed25519.Sign(h.Conf.DSAPriv, h.key[:])
399
400                 var enc []byte
401                 if h.Conf.Noise {
402                         enc = make([]byte, h.Conf.MTU-8)
403                 } else {
404                         enc = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
405                 }
406                 copy(enc, h.rServer[:])
407                 copy(enc[RSize:], h.rClient[:])
408                 copy(enc[RSize+RSize:], h.sClient[:])
409                 copy(enc[RSize+RSize+SSize:], sign[:])
410                 if h.Conf.Encless {
411                         enc, err = EnclessEncode(h.key, h.rNonceNext(1), enc)
412                         if err != nil {
413                                 panic(err)
414                         }
415                 } else {
416                         salsa20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)
417                 }
418
419                 // Send that to server
420                 h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
421                 h.LastPing = time.Now()
422         } else
423         // ENC(K, R+2, RC) + IDtag
424         if h.key != nil && ((!h.Conf.Encless && len(data) >= 16) ||
425                 (h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
426                 var err error
427                 // Decrypt rClient
428                 var dec []byte
429                 if h.Conf.Encless {
430                         dec, err = EnclessDecode(h.key, h.rNonceNext(2), data[:len(data)-8])
431                         if err != nil {
432                                 log.Println("Unable to decode packet from", h.addr, err)
433                                 return nil
434                         }
435                         dec = dec[:RSize]
436                 } else {
437                         dec = make([]byte, RSize)
438                         salsa20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
439                 }
440                 if subtle.ConstantTimeCompare(dec, h.rClient[:]) != 1 {
441                         log.Println("Invalid client's random number with", h.addr)
442                         return nil
443                 }
444
445                 // Switch peer
446                 peer := newPeer(
447                         true,
448                         h.addr,
449                         h.conn,
450                         h.Conf,
451                         keyFromSecrets(h.sServer[:], h.sClient[:]),
452                 )
453                 h.LastPing = time.Now()
454                 return peer
455         } else {
456                 log.Println("Invalid handshake stage from", h.addr)
457         }
458         return nil
459 }