VERSION | 2 +- doc/developer.texi | 2 ++ doc/download.texi | 14 ++++++++------ doc/govpn.texi | 2 +- doc/handshake.texi | 18 ++++++++++-------- doc/handshake.txt | 4 ++-- doc/installation.texi | 25 ++++++++++--------------- doc/integrity.texi | 15 +++++++++++++++ doc/keywords.texi | 2 +- doc/news.texi | 12 +++++++++++- doc/overview.texi | 5 +++-- doc/precautions.texi | 6 +++--- doc/sources.texi | 22 ++++++++++++++++++++++ doc/thanks.texi | 16 +++++++++------- doc/verifierstruct.texi | 2 +- handshake.go | 58 +++++++++++++++++++++++++++++++++-------------------- transport.go | 49 ++++++++++++++++++++++++------------------------- transport_test.go | 2 +- utils/makedist.sh | 7 ++++++- diff --git a/VERSION b/VERSION index 9f55b2ccb5f234fc6b87ada62389a3d73815d0d1..8c50098d8aed57b02fd10f40a670a7c673b7c5a5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0 +3.1 diff --git a/doc/developer.texi b/doc/developer.texi index 3fd23ed817fae43d18409af8c9862dc351163aad..be57f2c8a3f117d87b6988c8154b2a1324281804 100644 --- a/doc/developer.texi +++ b/doc/developer.texi @@ -11,6 +11,8 @@ @url{http://cr.yp.to/mac.html, Poly1305} @item Password authenticated key agreement DH-A-EKE powered by @url{http://cr.yp.to/ecdh.html, Curve25519} and @url{http://ed25519.cr.yp.to/, Ed25519} +@item DH elliptic-curve point encoding for public keys +@url{http://elligator.cr.yp.to/, Elligator} @item Key derivation function for verifier generation @url{https://en.wikipedia.org/wiki/PBKDF2, PBKDF2} based on @url{https://en.wikipedia.org/wiki/SHA-2, SHA-512} diff --git a/doc/download.texi b/doc/download.texi index 9c6193b8f707a65e44b01941a395e85412c3068e..68e596a2ffd8411ecb49e54dc397b47f9b6edf13 100644 --- a/doc/download.texi +++ b/doc/download.texi @@ -1,3 +1,6 @@ +@node Prepared tarballs +@section Prepared tarballs + You can obtain releases source code prepared tarballs from the links below: @multitable {XXXXX} {XXXX KiB} {link sign} {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx} @@ -23,13 +26,12 @@ @item 2.4 @tab 42 KiB @tab @url{download/govpn-2.4.tar.xz, link} @url{download/govpn-2.4.tar.xz.sig, sign} @tab @code{df45225bac2384c5eed73c5cdb05dc3581495e08d365317beb03a2487d46b98c} +@item 3.0 @tab 53 KiB +@tab @url{download/govpn-3.0.tar.xz, link} @url{download/govpn-3.0.tar.xz.sig, sign} +@tab @code{12579c5c3cccfe73c66b5893335bc70c42d7b13b8e94c7751ec65d421eaff9a5} + @end multitable -Also you can try it's @ref{Contacts, .onion} version. +Also you can try its @ref{Contacts, .onion} version. Sourceforge.net also provides mirror for the files above: @url{http://sourceforge.net/projects/govpn/files/}. - -You can obtain it's development source code by cloning -Git repository: @code{git clone https://github.com/stargrave/govpn.git}. -Pay attention that it does not contain compiled documentation and is not -recommended for porters because of that. diff --git a/doc/govpn.texi b/doc/govpn.texi index fe842b3a04d73c9f6944f52d6b60d629836f3d12..a22e85f98efe9e633c825c5a31f348f22e8b33b7 100644 --- a/doc/govpn.texi +++ b/doc/govpn.texi @@ -7,7 +7,7 @@ @copying This manual is for GoVPN -- simple secure free software virtual private network (VPN) daemon, written entirely on Go programming language. -Copyright @copyright{} 2014-2015 Sergey Matveev @email{stargrave@@stargrave.org} +Copyright @copyright{} 2014-2015 @email{stargrave@@stargrave.org, Sergey Matveev} @quotation Permission is granted to copy, distribute and/or modify this document diff --git a/doc/handshake.texi b/doc/handshake.texi index 6f1e37e32a72098cb00abb3b28238fe8ae1cfcf2..0b7f4bd840dea447bbaaab0d5e895c26f59165b9 100644 --- a/doc/handshake.texi +++ b/doc/handshake.texi @@ -23,19 +23,20 @@ @code{DSAPub}. @code{H()} is @emph{HSalsa20} hash function. @item Client generates DH keypair: @code{CDHPub} and @code{CDHPriv}. Also it generates random 64-bit @code{R} that is used as a nonce for -symmetric encryption. +symmetric encryption. @code{El()} is Elligator point encoding algorithm. @end enumerate @strong{Interaction stage}: @enumerate @item -@verb{|R + enc(H(DSAPub), R, CDHPub) + IDtag -> Server|} [48 bytes] +@verb{|R + enc(H(DSAPub), R, El(CDHPub)) + IDtag -> Server|} [48 bytes] @item @itemize @bullet @item Server remembers client address. -@item Decrypts @code{CDHPub}. +@item Decrypts @code{El(CDHPub)}. +@item Inverts @code{El()} encoding and gets @code{CDHPub}. @item Generates DH keypair: @code{SDHPriv}/@code{SDHPub}. @item Computes common shared key @code{K = H(DH(SDHPriv, CDHPub))}. @item Generates 64-bit random number @code{RS}. @@ -43,11 +44,12 @@ @item Generates 256-bit pre-master secret @code{SS}. @end itemize @item -@verb{|enc(H(DSAPub), R+1, SDHPub) + enc(K, R, RS + SS) + IDtag -> Client|} [80 bytes] +@verb{|enc(H(DSAPub), R+1, El(SDHPub)) + enc(K, R, RS + SS) + IDtag -> Client|} [80 bytes] @item @itemize @bullet -@item Client decrypts @code{SDHPub}. +@item Client decrypts @code{El(SDHPub)}. +@item Inverts @code{El()} encoding and gets @code{SDHPub}. @item Computes @code{K}. @item Decrypts @code{RS} and @code{SS}. @item Remembers @code{SS}. @@ -64,9 +66,9 @@ @itemize @bullet @item Server decrypts @code{RS}, @code{RC}, @code{SC}, @code{Sign(DSAPriv, K)}. - @item Compares @code{RS} with it's own one sent before. Server + @item Compares @code{RS} with its own one sent before. Server decrypts @code{RS}, @code{RC}, @code{SC} with key @code{K}, compares - @code{RS} with it's own one sent before. + @code{RS} with its own one sent before. @item Verifies @code{K} signature with verifier @code{DSAPub}. @@ -80,7 +82,7 @@ @item @itemize @bullet @item Client decrypts @code{RC} -@item Compares with it's own one sent before. +@item Compares with its own one sent before. @item Computes final session encryption key as server did. @end itemize diff --git a/doc/handshake.txt b/doc/handshake.txt index 8c3eb3898be080c96303456a928645b296292610..8804ae1cc684211b3f248d5cbf22824920de57cd 100644 --- a/doc/handshake.txt +++ b/doc/handshake.txt @@ -4,12 +4,12 @@ participant Server Client -> Client : R=rand(64bit) Client -> Client : CDHPriv=rand(256bit) -Client -> Server : R, enc(H(DSAPub), R, CDHPub) +Client -> Server : R, enc(H(DSAPub), R, El(CDHPub)) Server -> Server : SDHPriv=rand(256bit) Server -> Server : K=H(DH(SDHPriv, CDHPub)) Server -> Server : RS=rand(64bit) Server -> Server : SS=rand(256bit) -Server -> Client : enc(H(DSAPub), R+1, SDHPub); enc(K, R, RS+SS) +Server -> Client : enc(H(DSAPub), R+1, El(SDHPub)); enc(K, R, RS+SS) Client -> Client : K=H(DH(CDHPriv, SDHPub)) Client -> Client : RC=rand(64bit); SC=rand(256bit) Client -> Server : enc(K, R+1, RS+RC+SC+Sign(DSAPriv, K)) diff --git a/doc/installation.texi b/doc/installation.texi index 13d215919fbcbc194eba6f804edc6c1ffcc60fd1..727647696575480551788b5a4bc2e4eca41fda5e 100644 --- a/doc/installation.texi +++ b/doc/installation.texi @@ -19,20 +19,7 @@ @item @code{github.com/agl/ed25519} @tab All @tab BSD 3-Clause @item @code{github.com/bigeagle/water} @tab GNU/Linux @tab BSD 3-Clause @end multitable -@include download.texi - -You @strong{have to} verify downloaded archives integrity and check -their signature to be sure that you have got trusted, untampered -software. For integrity and authentication of downloaded binaries -@url{https://www.gnupg.org/, The GNU Privacy Guard} is used. You must -download signature provided with the tarball. - -For the very first time you have to import signing public keys. They -are provided below, but be sure that you are reading them from the -trusted source. Alternatively check this page from -@ref{Contacts, other sources} and look for the mailing list announcements. - -For example you can get tarball, set proper @code{$GOPATH} and run +You can get tarball, set proper @code{$GOPATH} and run @code{make} (that will install all necessary libraries and build @emph{govpn-client}, @emph{govpn-server}, @emph{govpn-verifier} binaries: @@ -48,4 +35,12 @@ % export GOPATH=$(pwd)/govpn:$GOPATH % gmake -C govpn/src/govpn all @end example -@include pubkey.texi +@menu +* Prepared tarballs:: +* Development source code:: +* Tarballs integrity check:: +@end menu + +@include download.texi +@include sources.texi +@include integrity.texi diff --git a/doc/integrity.texi b/doc/integrity.texi new file mode 100644 index 0000000000000000000000000000000000000000..01badc5e008af03bf8eb4c866aeb73f2d5e4cd15 --- /dev/null +++ b/doc/integrity.texi @@ -0,0 +1,15 @@ +@node Tarballs integrity check +@section Tarballs integrity check + +You @strong{have to} verify downloaded archives integrity and check +their signature to be sure that you have got trusted, untampered +software. For integrity and authentication of downloaded binaries +@url{https://www.gnupg.org/, The GNU Privacy Guard} is used. You must +download signature provided with the tarball. + +For the very first time you need to import signing public keys. They +are provided below, but be sure that you are reading them from the +trusted source. Alternatively check this page from +@ref{Contacts, other sources} and look for the mailing list announcements. + +@include pubkey.texi diff --git a/doc/keywords.texi b/doc/keywords.texi index 39a20e33dc439b44312ebc9a965701d04d04ab9d..a513724a640648574277389211b6c56f4627447c 100644 --- a/doc/keywords.texi +++ b/doc/keywords.texi @@ -2,7 +2,7 @@ Some keywords describing this project: encryption, authentication, key exchange, EKE, Diffie-Hellman, DH, DH-EKE, Augmented EKE, A-EKE, security, encrypted key exchange, 128-bit margin, DPI, censorship, resistance, free software, GPLv3+, reviewability, easy, simple, -Curve25519, Ed25519, SHA-512, Salsa20, Poly1305, AEAD, XTEA, PBKDF2, +Curve25519, Ed25519, Elligator, SHA-512, Salsa20, Poly1305, AEAD, XTEA, PBKDF2, PRP, signatures, asymmetric cryptography, zero-knowledge password proof, PAKE, password, passphrase, password authenticated key exchange, perfect forward secrecy, PFS, MAC, nonce, verifier, rehandshake, heartbeat, diff --git a/doc/news.texi b/doc/news.texi index 75ec725137b1b9640dd0dc3bb7e0b1505ff05aa8..be9bc6043e93c7becc7af86aaffd571b5bd01874 100644 --- a/doc/news.texi +++ b/doc/news.texi @@ -2,6 +2,16 @@ @node News @unnumbered News @table @strong +@item Release 3.1 +@itemize @bullet +@item +Diffie-Hellman public keys are encoded with Elligator algorithm when +sending over the wire, making them indistinguishable from the random +strings, preventing detection of successful decryption try when guessing +passwords (that are used to create DSA public keys). But this will +consume twice entropy for DH key generation in average. +@end itemize + @item Release 3.0 @itemize @bullet @item @@ -23,7 +33,7 @@ packets became smaller @item Ability to hide underlying packets lengths by appending noise, junk -data during transmission. Each packet can be fill up-ed to it's +data during transmission. Each packet can be fill up-ed to its maximal MTU size. @item diff --git a/doc/overview.texi b/doc/overview.texi index f6b81ac771075f02233896e49d58619ac6f45b16..dc68994470bfa4776cb60685c1fd9545b5e4d260 100644 --- a/doc/overview.texi +++ b/doc/overview.texi @@ -20,8 +20,9 @@ function based on @url{https://en.wikipedia.org/wiki/SHA-2, SHA-512} hash function, @url{https://en.wikipedia.org/wiki/Encrypted_key_exchange, Diffie-Hellman Augmented Encrypted Key Exchange} -(DH-A-EKE) powered by @url{http://cr.yp.to/ecdh.html, Curve25519} and -@url{http://ed25519.cr.yp.to/, Ed25519} signatures. +(DH-A-EKE) powered by @url{http://cr.yp.to/ecdh.html, Curve25519}, +@url{http://ed25519.cr.yp.to/, Ed25519} signatures and +@url{http://elligator.cr.yp.to/, Elligator} curve-point encoding. Strong @url{https://en.wikipedia.org/wiki/Zero-knowledge_password_proof, zero-knowledge} mutual authentication with key exchange stage is invulnerable diff --git a/doc/precautions.texi b/doc/precautions.texi index 93b179e427f6829246d6a45e4b70bb0cb0f8068e..cd759ea72708dd0503cb77fd01d3f226c0b6f3f5 100644 --- a/doc/precautions.texi +++ b/doc/precautions.texi @@ -3,13 +3,13 @@ @unnumbered Precautions The very important precaution is the @strong{cryptographically good} pseudo random number generator. GoVPN uses native operating system PRNG -as entropy source. You have no way to check it's quality in closed +as entropy source. You have no way to check its quality in closed source code operating systems, so it is recommended not to use them if you really needs security. Moreover it is possible that those OS leaks information about possible PRNG states. And at least Apple OS X and Microsoft Windows are already known to have weak CSPRNGs. -GoVPN could use it's own PRNG implementation like +GoVPN could use its own PRNG implementation like @url{https://www.schneier.com/fortuna.html, Fortuna}, but it is much easier to use the right OS, to use free software. @@ -19,6 +19,6 @@ If it fails, produces equal values at least once, then all you traffic related to that key could be decrypted. We use password (passphrase) authentication, so overall security fully -depends on it's strength. So you should use long, high-entropy +depends on its strength. So you should use long, high-entropy passphrases. Also remember to keep passphrase on temporary file as described in @ref{Verifier}. diff --git a/doc/sources.texi b/doc/sources.texi new file mode 100644 index 0000000000000000000000000000000000000000..acecea741bf7b6cf4b9243149e0c0612fdf5e5c8 --- /dev/null +++ b/doc/sources.texi @@ -0,0 +1,22 @@ +@node Development source code +@section Development source code + +Development source contains the latest version of the code. It may be +buggy. Also it does not contain compiled documentation and is not +recommended for porters because of that. + +You can obtain it by cloning Git repository: +@code{git clone https://github.com/stargrave/govpn.git}. + +Also there is mirror of dependent libraries for safety if their native +repositories will be unavailable (they are seldom updated): + +@multitable @columnfractions .50 .50 +@headitem Software/library @tab Mirror +@item @code{govpn} @tab @url{git://git.cypherpunks.ru/govpn.git} +@item @code{golang.org/x/crypto/poly1305} @tab @url{git://git.cypherpunks.ru/crypto.git} +@item @code{golang.org/x/crypto/salsa20} @tab @url{git://git.cypherpunks.ru/crypto.git} +@item @code{golang.org/x/crypto/xtea} @tab @url{git://git.cypherpunks.ru/crypto.git} +@item @code{golang.org/x/crypto/pbkdf2} @tab @url{git://git.cypherpunks.ru/crypto.git} +@item @code{github.com/agl/ed25519} @tab @url{git://git.cypherpunks.ru/ed25519.git} +@end multitable diff --git a/doc/thanks.texi b/doc/thanks.texi index 69223702f4e025fee3b04e6f777eefbe98ab78bd..5d68d1c217af2b4d01ae73a1b19db86e90da6ea2 100644 --- a/doc/thanks.texi +++ b/doc/thanks.texi @@ -4,16 +4,18 @@ @itemize @bullet @item @url{https://www.schneier.com/books/applied_cryptography/, Applied Cryptography} -@copyright{} 1996 Bruce Schneier +@copyright{} 1996 Bruce Schneier. @item @url{http://tnlandforms.us/cns05/speke.pdf, Strong Password-Only Authenticated Key Exchange} -@copyright{} 1996 David P. Jablon +@copyright{} 1996 David P. Jablon. @item @url{https://www.cs.columbia.edu/~smb/papers/aeke.pdf, Augmented Encrypted Key Exchange}: a Password-Based Protocol Secure Against Dictionary Attacks and Password -File Compromise @copyright{} Steven M. Belloving, Michael Merrit -@item @url{http://cr.yp.to/ecdh.html, A state-of-the-art Diffie-Hellman function} -@item @url{http://cr.yp.to/snuffle.html, Snuffle 2005: the Salsa20 encryption function} -@item @url{http://cr.yp.to/mac.html, A state-of-the-art message-authentication code} -@item @url{http://ed25519.cr.yp.to/, Ed25519: high-speed high-security signatures} +File Compromise @copyright{} Steven M. Belloving, Michael Merrit. +@item @url{http://cr.yp.to/ecdh.html, A state-of-the-art Diffie-Hellman function}. +@item @url{http://cr.yp.to/snuffle.html, Snuffle 2005: the Salsa20 encryption function}. +@item @url{http://cr.yp.to/mac.html, A state-of-the-art message-authentication code}. +@item @url{http://ed25519.cr.yp.to/, Ed25519: high-speed high-security signatures}. +@item @email{watsonbladd@@gmail.com, Watson Ladd} for suggestion of + @url{http://elligator.cr.yp.to/, Elligator} encoding. @end itemize diff --git a/doc/verifierstruct.texi b/doc/verifierstruct.texi index 3b969dc07ac09f57752f228fcc38216e41473002..b508b483536d4b9e4aebef987362d126b42abe5d 100644 --- a/doc/verifierstruct.texi +++ b/doc/verifierstruct.texi @@ -3,7 +3,7 @@ @section Verifier structure Verifier is a derivative of the password. It is resistant to dictionary attacks and can not be used for authentication (only -it's verifying). +its verifying). @verbatim SOURCE = PBKDF2(SALT=PeerId, PASSWORD, 1<<16, SHA512) diff --git a/handshake.go b/handshake.go index 0fee82c77d0e70db8d23d8febf4aaa8021f92394..73cb4e2d35f39c3256e81d278328d30e38ff6c3b 100644 --- a/handshake.go +++ b/handshake.go @@ -27,6 +27,7 @@ "net" "time" "github.com/agl/ed25519" + "github.com/agl/ed25519/extra25519" "golang.org/x/crypto/curve25519" "golang.org/x/crypto/salsa20" "golang.org/x/crypto/salsa20/salsa" @@ -100,12 +101,18 @@ binary.PutUvarint(nonce, nonceCurrent+count) return nonce } -func dhPrivGen() *[32]byte { - dh := new([32]byte) - if _, err := rand.Read(dh[:]); err != nil { - panic("Can not read random for DH private key") +func dhKeypairGen() (*[32]byte, *[32]byte) { + priv := new([32]byte) + pub := new([32]byte) + repr := new([32]byte) + reprFound := false + for !reprFound { + if _, err := rand.Read(priv[:]); err != nil { + panic("Can not read random for DH private key") + } + reprFound = extra25519.ScalarBaseMult(pub, repr, priv) } - return dh + return priv, repr } func dhKeyGen(priv, pub *[32]byte) *[32]byte { @@ -146,16 +153,15 @@ // First handshake packet will be sent immediately. func HandshakeStart(conf *PeerConf, conn *net.UDPConn, addr *net.UDPAddr) *Handshake { state := HandshakeNew(addr, conf) - state.dhPriv = dhPrivGen() - dhPub := new([32]byte) - curve25519.ScalarBaseMult(dhPub, state.dhPriv) + var dhPubRepr *[32]byte + state.dhPriv, dhPubRepr = dhKeypairGen() state.rNonce = new([RSize]byte) if _, err := rand.Read(state.rNonce[:]); err != nil { panic("Can not read random for handshake nonce") } enc := make([]byte, 32) - salsa20.XORKeyStream(enc, dhPub[:], state.rNonce[:], state.dsaPubH) + salsa20.XORKeyStream(enc, dhPubRepr[:], state.rNonce[:], state.dsaPubH) data := append(state.rNonce[:], enc...) data = append(data, idTag(state.Conf.Id, state.rNonce[:])...) if _, err := conn.WriteTo(data, addr); err != nil { @@ -171,23 +177,29 @@ // If this is the final handshake message, then new Peer object // will be created and used as a transport. If no mutually // authenticated Peer is ready, then return nil. func (h *Handshake) Server(conn *net.UDPConn, data []byte) *Peer { - // R + ENC(H(DSAPub), R, CDHPub) + IDtag + // R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag if len(data) == 48 && h.rNonce == nil { - // Generate private DH key - h.dhPriv = dhPrivGen() - dhPub := new([32]byte) - curve25519.ScalarBaseMult(dhPub, h.dhPriv) + // Generate DH keypair + var dhPubRepr *[32]byte + h.dhPriv, dhPubRepr = dhKeypairGen() h.rNonce = new([RSize]byte) copy(h.rNonce[:], data[:RSize]) // Decrypt remote public key and compute shared key - dec := new([32]byte) - salsa20.XORKeyStream(dec[:], data[RSize:RSize+32], h.rNonce[:], h.dsaPubH) - h.key = dhKeyGen(h.dhPriv, dec) + cDHRepr := new([32]byte) + salsa20.XORKeyStream( + cDHRepr[:], + data[RSize:RSize+32], + h.rNonce[:], + h.dsaPubH, + ) + cDH := new([32]byte) + extra25519.RepresentativeToPublicKey(cDH, cDHRepr) + h.key = dhKeyGen(h.dhPriv, cDH) encPub := make([]byte, 32) - salsa20.XORKeyStream(encPub, dhPub[:], h.rNonceNext(1), h.dsaPubH) + salsa20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH) // Generate R* and encrypt them h.rServer = new([RSize]byte) @@ -259,16 +271,18 @@ // will be created and used as a transport. If no mutually // authenticated Peer is ready, then return nil. func (h *Handshake) Client(conn *net.UDPConn, data []byte) *Peer { switch len(data) { - case 80: // ENC(H(DSAPub), R+1, SDHPub) + ENC(K, R, RS + SS) + IDtag + case 80: // ENC(H(DSAPub), R+1, El(SDHPub)) + ENC(K, R, RS + SS) + IDtag if h.key != nil { log.Println("Invalid handshake stage from", h.addr) return nil } // Decrypt remote public key and compute shared key - dec := new([32]byte) - salsa20.XORKeyStream(dec[:], data[:32], h.rNonceNext(1), h.dsaPubH) - h.key = dhKeyGen(h.dhPriv, dec) + sDHRepr := new([32]byte) + salsa20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH) + sDH := new([32]byte) + extra25519.RepresentativeToPublicKey(sDH, sDHRepr) + h.key = dhKeyGen(h.dhPriv, sDH) // Decrypt Rs decRs := make([]byte, RSize+SSize) diff --git a/transport.go b/transport.go index ddcfbf90dc28f21904f3230de0c6f9e5cea0adb4..f46eeefb62b3aae5c9af6fbebe46705d9688e1b7 100644 --- a/transport.go +++ b/transport.go @@ -21,7 +21,6 @@ import ( "encoding/binary" "io" - "log" "net" "time" @@ -78,6 +77,8 @@ nonceRecv uint64 frame []byte nonce []byte pktSize uint64 + size int + now time.Time // Statistics BytesIn int64 @@ -269,18 +270,18 @@ // ConnListen'es synchronization channel used to tell him that he is // free to receive new packets. Authenticated and decrypted packets // 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) + p.size = len(udpPkt) copy(p.buf, Emptiness) - copy(p.tag[:], udpPkt[size-poly1305.TagSize:]) - copy(p.buf[S20BS:], udpPkt[NonceSize:size-poly1305.TagSize]) + copy(p.tag[:], udpPkt[p.size-poly1305.TagSize:]) + copy(p.buf[S20BS:], udpPkt[NonceSize:p.size-poly1305.TagSize]) salsa20.XORKeyStream( - p.buf[:S20BS+size-poly1305.TagSize], - p.buf[:S20BS+size-poly1305.TagSize], + p.buf[:S20BS+p.size-poly1305.TagSize], + p.buf[:S20BS+p.size-poly1305.TagSize], udpPkt[:NonceSize], p.Key, ) copy(p.keyAuth[:], p.buf[:SSize]) - if !poly1305.Verify(p.tag, udpPkt[:size-poly1305.TagSize], p.keyAuth) { + if !poly1305.Verify(p.tag, udpPkt[:p.size-poly1305.TagSize], p.keyAuth) { ready <- struct{}{} p.FramesUnauth++ return false @@ -294,7 +295,7 @@ return false } ready <- struct{}{} p.FramesIn++ - p.BytesIn += int64(size) + p.BytesIn += int64(p.size) p.LastPing = time.Now() p.NonceRecv = p.nonceRecv p.pktSize, _ = binary.Uvarint(p.buf[S20BS : S20BS+PktSizeSize]) @@ -308,8 +309,8 @@ tap.Write(p.frame) return true } -type WriteToer interface { - WriteTo([]byte, net.Addr) (int, error) +type WriteToUDPer interface { + WriteToUDP([]byte, *net.UDPAddr) (int, error) } // Process incoming Ethernet packet. @@ -317,19 +318,19 @@ // ethPkt is received data, conn is our outgoing connection. // ready channel is TAPListen's synchronization channel used to tell him // that he is free to receive new packets. Encrypted and authenticated // packets will be sent to remote Peer side immediately. -func (p *Peer) EthProcess(ethPkt []byte, conn WriteToer, ready chan struct{}) { - now := time.Now() - size := len(ethPkt) +func (p *Peer) EthProcess(ethPkt []byte, conn WriteToUDPer, ready chan struct{}) { + p.now = time.Now() + p.size = len(ethPkt) // If this heartbeat is necessary - if size == 0 && !p.LastSent.Add(p.Timeout).Before(now) { + if p.size == 0 && !p.LastSent.Add(p.Timeout).Before(p.now) { return } copy(p.buf, Emptiness) - if size > 0 { + if p.size > 0 { copy(p.buf[S20BS+PktSizeSize:], ethPkt) ready <- struct{}{} - binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(size)) - p.BytesPayloadOut += int64(size) + binary.PutUvarint(p.buf[S20BS:S20BS+PktSizeSize], uint64(p.size)) + p.BytesPayloadOut += int64(p.size) } else { p.HeartbeatSent++ } @@ -345,7 +346,7 @@ copy(p.keyAuth[:], p.buf[:SSize]) if p.NoiseEnable { p.frame = p.buf[S20BS-NonceSize : S20BS+MTU-NonceSize-poly1305.TagSize] } else { - p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+size] + p.frame = p.buf[S20BS-NonceSize : S20BS+PktSizeSize+p.size] } poly1305.Sum(p.tag, p.frame, p.keyAuth) @@ -354,13 +355,11 @@ p.FramesOut++ if p.CPRCycle != time.Duration(0) { p.willSentCycle = p.LastSent.Add(p.CPRCycle) - if p.willSentCycle.After(now) { - time.Sleep(p.willSentCycle.Sub(now)) - now = p.willSentCycle + if p.willSentCycle.After(p.now) { + time.Sleep(p.willSentCycle.Sub(p.now)) + p.now = p.willSentCycle } } - p.LastSent = now - if _, err := conn.WriteTo(append(p.frame, p.tag[:]...), p.Addr); err != nil { - log.Println("Error sending UDP", err) - } + p.LastSent = p.now + conn.WriteToUDP(append(p.frame, p.tag[:]...), p.Addr) } diff --git a/transport_test.go b/transport_test.go index 0dc54f992b24210a9623c8a60683651a5d6656c1..51f0e6e322f17efa25edfabe9484c8a587b6e134 100644 --- a/transport_test.go +++ b/transport_test.go @@ -40,7 +40,7 @@ } type Dummy struct{} -func (d *Dummy) WriteTo(b []byte, addr net.Addr) (int, error) { +func (d *Dummy) WriteToUDP(b []byte, addr *net.UDPAddr) (int, error) { ciphertext = b return len(b), nil } diff --git a/utils/makedist.sh b/utils/makedist.sh index 9e2e3656c38b88678b980701ed703a3be2732ef3..6ff776ca7131767dc9d6d4d5c793efe8ee54b19f 100755 --- a/utils/makedist.sh +++ b/utils/makedist.sh @@ -9,7 +9,12 @@ cd $tmp/govpn-$release git checkout $release rm -fr .git find . -name .gitignore -delete -echo > doc/download.texi +cat > doc/download.texi <