]> Cypherpunks.ru repositories - govpn.git/commitdiff
Replace (X)Salsa20 with ChaCha20
authorSergey Matveev <stargrave@stargrave.org>
Sat, 29 Oct 2016 13:42:01 +0000 (16:42 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sat, 29 Oct 2016 14:14:45 +0000 (17:14 +0300)
Theoreticall it is more faster and secure.

14 files changed:
VERSION
doc/developer.texi
doc/encless.texi
doc/news.ru.texi
doc/news.texi
doc/transport.texi
src/chacha20 [new symlink]
src/cypherpunks.ru/govpn/aont/oaep.go
src/cypherpunks.ru/govpn/cnw/cnw.go
src/cypherpunks.ru/govpn/encless.go
src/cypherpunks.ru/govpn/encless_test.go
src/cypherpunks.ru/govpn/handshake.go
src/cypherpunks.ru/govpn/peer.go
utils/makedist.sh

diff --git a/VERSION b/VERSION
index e0ea36feef6e828ce8587989537a827d0c3c98ed..4fedf1d20e15761409d6e4e3bf99c0beb499fdfe 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.0
+7.0
index b12d5e15d8e860cb2d05f5895378f282e2ca948b..15e87800a314b44604730747b9a0610ab91c8f02 100644 (file)
@@ -5,7 +5,7 @@ Pay attention how to get @ref{Sources, development source code}.
 
 @table @asis
 @item Data encryption
-    @url{http://cr.yp.to/snuffle.html, Salsa20}.
+    @url{https://cr.yp.to/chacha.html, ChaCha20}.
 @item Message authentication
     @url{https://cr.yp.to/mac.html, Poly1305}.
 @item Nonce and identity obfuscation
@@ -25,7 +25,7 @@ Pay attention how to get @ref{Sources, development source code}.
     @url{http://theory.lcs.mit.edu/~cis/pubs/rivest/fusion.ps,
     All-Or-Nothing-Transformed} (based on
     @url{http://cseweb.ucsd.edu/~mihir/papers/oaep.html, OAEP} using
-    Salsa20 with BLAKE2b-256 based
+    ChaCha20 with BLAKE2b-256 based
     @url{http://crypto.stanford.edu/~dabo/abstracts/saep.html, SAEP+}
     checksums) data with 128-bits of feeded random.
 @item Packet overhead
index 6d694b2a984217740f0dff2c321aaa088c28d4c3..9513d6ce67f5bd8b473b0a0cb44cabd478e3666f 100644 (file)
@@ -8,7 +8,7 @@ some countries forbids usage of encryption (but again not the
 authentication).
 
 GoVPN provides special encryptionless mode of operation. In this mode it
-replaces Salsa20 function used for confidentiality with rather
+replaces ChaCha20 function used for confidentiality with rather
 well-known @url{http://people.csail.mit.edu/rivest/chaffing-980701.txt,
 Chaffing-and-Winnowing} (CnW) technology. This is rather traffic and
 resource hungry algorithm, so we use it after
index 47ba43bc1607d386173505a9fd3ccbbc483e5746..db4a6edfea4c2c2208dc58e593dd87711c6054e5 100644 (file)
@@ -1,6 +1,13 @@
 @node Новости
 @section Новости
 
+@node Релиз 7.0
+@subsection Релиз 7.0
+@itemize
+@item (X)Salsa20 заменён на ChaCha20. Теоретически он должен быть
+быстрее и более безопасным.
+@end itemize
+
 @node Релиз 6.0
 @subsection Релиз 6.0
 @itemize
index 631c5940ac541920570e9a02f9e807d232a872fe..10a2aab6d134519e72530c49d4fb0f33d7dff6e0 100644 (file)
@@ -3,6 +3,13 @@
 
 See also this page @ref{Новости, on russian}.
 
+@node Release 7.0
+@section Release 7.0
+@itemize
+@item (X)Salsa20 is replaced with ChaCha20. Theoretically it should be
+faster and more secure.
+@end itemize
+
 @node Release 6.0
 @section Release 6.0
 @itemize
index 812322528f03019d4b882dab6e925ebdd386afa4..e5f5abba9eba15dec245489f2aa53c807d007b5f 100644 (file)
@@ -2,7 +2,7 @@
 @section Transport protocol
 
 @verbatim
-     NONCE = 64bit(MAC(MAC_KEY, SERIAL))
+     NONCE = 64bit(ZEROS) || 64bit(MAC(MAC_KEY, SERIAL))
    PAYLOAD = DATA || PAD [|| ZEROS]
 CIPHERTEXT = ENCRYPT(KEY, NONCE, PAYLOAD)
        TAG = AUTH(AUTH_KEY, CIPHERTEXT || NONCE)
@@ -13,16 +13,16 @@ CIPHERTEXT = ENCRYPT(KEY, NONCE, PAYLOAD)
 client (to server) messages, evens for server (to client) messages.
 
 @code{MAC} is BLAKE2b-MAC used to obfuscate @code{SERIAL}. MAC's key
-@code{MAC_KEY} is the first 256-bit of Salsa20's output with established
+@code{MAC_KEY} is the first 256-bit of ChaCha20's output with established
 common key and zero nonce (message nonces start from 1).
 
 @verbatim
 MAC_KEY = 256bit(ENCRYPT(KEY, 0))
 @end verbatim
 
-@code{ENCRYPT} is Salsa20 stream cipher, with established session
+@code{ENCRYPT} is ChaCha20 stream cipher, with established session
 @code{KEY} and obfuscated @code{SERIAL} used as a nonce. 512 bit of
-Salsa20's output is ignored and only remaining is XORed with ther data,
+ChaCha20's output is ignored and only remaining is XORed with ther data,
 encrypting it.
 
 @code{DATA} is padded using ISO/IEC 7816-4 format (@code{PAD} (0x80
@@ -30,7 +30,7 @@ byte) with optional @code{ZEROS} following), to fill up packet to
 conceal payload packet length.
 
 @code{AUTH} is Poly1305 authentication function. First 256 bits of
-Salsa20's output are used as a one-time key for @code{AUTH}.
+ChaCha20's output are used as a one-time key for @code{AUTH}.
 
 @verbatim
 AUTH_KEY = 256bit(ENCRYPT(KEY, NONCE))
diff --git a/src/chacha20 b/src/chacha20
new file mode 120000 (symlink)
index 0000000..95f85aa
--- /dev/null
@@ -0,0 +1 @@
+golang.org/x/crypto/chacha20poly1305/internal/chacha20
\ No newline at end of file
index 3d1a1c6731722eecef657ffa3a6e9074b7368d6e..4b780ba427ed2e6f87e8d5724ed2488b4f8e8f17 100644 (file)
@@ -30,7 +30,7 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // package PKG:
 //
 //     PKG = P1 || P2
-//      P1 = Salsa20(key=r, nonce=0x00, 0x00) XOR (M || BLAKE2b(r || M))
+//      P1 = ChaCha20(key=r, nonce=0x00, 0x00) XOR (M || BLAKE2b(r || M))
 //      P2 = BLAKE2b(P1) XOR r
 package aont
 
@@ -38,8 +38,8 @@ import (
        "crypto/subtle"
        "errors"
 
+       "chacha20"
        "golang.org/x/crypto/blake2b"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
@@ -48,7 +48,7 @@ const (
 )
 
 var (
-       dummyNonce []byte = make([]byte, 8)
+       dummyNonce *[16]byte = new([16]byte)
 )
 
 // Encode the data, produce AONT package. Data size will be larger than
@@ -63,9 +63,9 @@ func Encode(r *[RSize]byte, in []byte) ([]byte, error) {
        h.Write(r[:])
        h.Write(in)
        copy(out[len(in):], h.Sum(nil))
-       salsaKey := new([32]byte)
-       copy(salsaKey[:], r[:])
-       salsa20.XORKeyStream(out, out, dummyNonce, salsaKey)
+       chachaKey := new([32]byte)
+       copy(chachaKey[:], r[:])
+       chacha20.XORKeyStream(out, out, dummyNonce, chachaKey)
        h.Reset()
        h.Write(out[:len(in)+32])
        for i, b := range h.Sum(nil)[:RSize] {
@@ -85,14 +85,14 @@ func Decode(in []byte) ([]byte, error) {
                return nil, err
        }
        h.Write(in[:len(in)-RSize])
-       salsaKey := new([32]byte)
+       chachaKey := new([32]byte)
        for i, b := range h.Sum(nil)[:RSize] {
-               salsaKey[i] = b ^ in[len(in)-RSize+i]
+               chachaKey[i] = b ^ in[len(in)-RSize+i]
        }
        h.Reset()
-       h.Write(salsaKey[:RSize])
+       h.Write(chachaKey[:RSize])
        out := make([]byte, len(in)-RSize)
-       salsa20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, salsaKey)
+       chacha20.XORKeyStream(out, in[:len(in)-RSize], dummyNonce, chachaKey)
        h.Write(out[:len(out)-HSize])
        if subtle.ConstantTimeCompare(h.Sum(nil), out[len(out)-HSize:]) != 1 {
                return nil, errors.New("Invalid checksum")
index 931a0d11d62905ade2afad22227347254b0d54d2..c5d41a635afb3440558f19b3c351ccc1035a0229 100644 (file)
@@ -34,11 +34,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // one is over "0". If bit value is 1, then first is taken over "0" and
 // second is over "1".
 //
-// Poly1305 uses 256-bit one-time key. We generate it using XSalsa20 for
+// Poly1305 uses 256-bit one-time key. We generate it using ChaCha20 for
 // for the whole byte at once (16 MACs).
 //
-//     MACKey1, MACKey2, ... = XSalsa20(authKey, nonce, 0x00...)
-//     nonce = prefix || 0x00... || big endian byte number
+//     MACKey1, MACKey2, ... = ChaCha20(authKey, nonce, 0x00...)
+//     nonce = prefix || big endian byte number
 package cnw
 
 import (
@@ -46,8 +46,8 @@ import (
        "encoding/binary"
        "errors"
 
+       "chacha20"
        "golang.org/x/crypto/poly1305"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
@@ -65,15 +65,15 @@ func zero(in []byte) {
 func Chaff(authKey *[32]byte, noncePrfx, in []byte) []byte {
        out := make([]byte, len(in)*EnlargeFactor)
        keys := make([]byte, 8*64)
-       nonce := make([]byte, 24)
+       nonce := new([16]byte)
        copy(nonce[:8], noncePrfx)
        var i int
        var v byte
        tag := new([16]byte)
        macKey := new([32]byte)
        for n, b := range in {
-               binary.BigEndian.PutUint64(nonce[16:], uint64(n))
-               salsa20.XORKeyStream(keys, keys, nonce, authKey)
+               binary.BigEndian.PutUint64(nonce[8:], uint64(n))
+               chacha20.XORKeyStream(keys, keys, nonce, authKey)
                for i = 0; i < 8; i++ {
                        v = (b >> uint8(i)) & 1
                        copy(macKey[:], keys[64*i:64*i+32])
@@ -104,7 +104,7 @@ func Winnow(authKey *[32]byte, noncePrfx, in []byte) ([]byte, error) {
        }
        out := make([]byte, len(in)/EnlargeFactor)
        keys := make([]byte, 8*64)
-       nonce := make([]byte, 24)
+       nonce := new([16]byte)
        copy(nonce[:8], noncePrfx)
        var i int
        var v byte
@@ -116,8 +116,8 @@ func Winnow(authKey *[32]byte, noncePrfx, in []byte) ([]byte, error) {
        var is11 bool
        var is10 bool
        for n := 0; n < len(out); n++ {
-               binary.BigEndian.PutUint64(nonce[16:], uint64(n))
-               salsa20.XORKeyStream(keys, keys, nonce, authKey)
+               binary.BigEndian.PutUint64(nonce[8:], uint64(n))
+               chacha20.XORKeyStream(keys, keys, nonce, authKey)
                v = 0
                for i = 0; i < 8; i++ {
                        copy(macKey[:], keys[64*i:64*i+32])
index f9d9bbfe075e587e6fd16fd9e023a62a5f343537..bd42f1d5729349e1a4c3bf6fe2bb813445ee6249 100644 (file)
@@ -35,7 +35,7 @@ const (
 // encryption nor steganography) over All-Or-Nothing-Transformed data.
 // nonce is 64-bit nonce. Output data will be EnclessEnlargeSize larger.
 // It also consumes 64-bits of entropy.
-func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
+func EnclessEncode(authKey *[32]byte, nonce *[16]byte, in []byte) ([]byte, error) {
        r := new([aont.RSize]byte)
        var err error
        if _, err = io.ReadFull(Rand, r[:]); err != nil {
@@ -46,7 +46,7 @@ func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
                return nil, err
        }
        out := append(
-               cnw.Chaff(authKey, nonce, aonted[:aont.RSize]),
+               cnw.Chaff(authKey, nonce[8:], aonted[:aont.RSize]),
                aonted[aont.RSize:]...,
        )
        SliceZero(aonted[:aont.RSize])
@@ -54,10 +54,10 @@ func EnclessEncode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
 }
 
 // Decode EnclessEncode-ed data.
-func EnclessDecode(authKey *[32]byte, nonce, in []byte) ([]byte, error) {
+func EnclessDecode(authKey *[32]byte, nonce *[16]byte, in []byte) ([]byte, error) {
        var err error
        winnowed, err := cnw.Winnow(
-               authKey, nonce, in[:aont.RSize*cnw.EnlargeFactor],
+               authKey, nonce[8:], in[:aont.RSize*cnw.EnlargeFactor],
        )
        if err != nil {
                return nil, err
index 1f9fece30e3207999ec3a01a6d779888299d15e6..fc00d2708d753735bb501e3886c1ee8d4df1cde5 100644 (file)
@@ -35,9 +35,9 @@ func init() {
 }
 
 func TestEnclessSymmetric(t *testing.T) {
-       nonce := make([]byte, 8)
+       nonce := new([16]byte)
        f := func(pktNum uint64, in []byte) bool {
-               binary.BigEndian.PutUint64(nonce, pktNum)
+               binary.BigEndian.PutUint64(nonce[8:], pktNum)
                encoded, err := EnclessEncode(testKey, nonce, in)
                if err != nil {
                        return false
@@ -54,9 +54,9 @@ func TestEnclessSymmetric(t *testing.T) {
 }
 
 func BenchmarkEnclessEncode(b *testing.B) {
-       nonce := make([]byte, 8)
+       nonce := new([16]byte)
        data := make([]byte, 128)
-       io.ReadFull(Rand, nonce)
+       io.ReadFull(Rand, nonce[8:])
        io.ReadFull(Rand, data)
        b.ResetTimer()
        for i := 0; i < b.N; i++ {
@@ -65,9 +65,9 @@ func BenchmarkEnclessEncode(b *testing.B) {
 }
 
 func BenchmarkEnclessDecode(b *testing.B) {
-       nonce := make([]byte, 8)
+       nonce := new([16]byte)
        data := make([]byte, 128)
-       io.ReadFull(Rand, nonce)
+       io.ReadFull(Rand, nonce[8:])
        io.ReadFull(Rand, data)
        encoded, _ := EnclessEncode(testKey, nonce, data)
        b.ResetTimer()
index fb486f592aa86ff76417a4dcad8e732cd843878c..a3ef2b5cf536397c176678d38c8fcd4fff70d1d8 100644 (file)
@@ -25,11 +25,11 @@ import (
        "log"
        "time"
 
+       "chacha20"
        "github.com/agl/ed25519"
        "github.com/agl/ed25519/extra25519"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/curve25519"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
@@ -44,7 +44,7 @@ type Handshake struct {
        Conf     *PeerConf
        dsaPubH  *[ed25519.PublicKeySize]byte
        key      *[32]byte
-       rNonce   *[RSize]byte
+       rNonce   *[16]byte
        dhPriv   *[32]byte    // own private DH key
        rServer  *[RSize]byte // random string for authentication
        rClient  *[RSize]byte
@@ -88,10 +88,10 @@ func (h *Handshake) Zero() {
        }
 }
 
-func (h *Handshake) rNonceNext(count uint64) []byte {
-       nonce := make([]byte, RSize)
-       nonceCurrent, _ := binary.Uvarint(h.rNonce[:])
-       binary.PutUvarint(nonce, nonceCurrent+count)
+func (h *Handshake) rNonceNext(count uint64) *[16]byte {
+       nonce := new([16]byte)
+       nonceCurrent, _ := binary.Uvarint(h.rNonce[8:])
+       binary.PutUvarint(nonce[8:], nonceCurrent+count)
        return nonce
 }
 
@@ -153,8 +153,8 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
        var dhPubRepr *[32]byte
        state.dhPriv, dhPubRepr = dhKeypairGen()
 
-       state.rNonce = new([RSize]byte)
-       if _, err := io.ReadFull(Rand, state.rNonce[:]); err != nil {
+       state.rNonce = new([16]byte)
+       if _, err := io.ReadFull(Rand, state.rNonce[8:]); err != nil {
                log.Fatalln("Error reading random for nonce:", err)
        }
        var enc []byte
@@ -166,15 +166,15 @@ func HandshakeStart(addr string, conn io.Writer, conf *PeerConf) *Handshake {
        copy(enc, dhPubRepr[:])
        if conf.Encless {
                var err error
-               enc, err = EnclessEncode(state.dsaPubH, state.rNonce[:], enc)
+               enc, err = EnclessEncode(state.dsaPubH, state.rNonce, enc)
                if err != err {
                        panic(err)
                }
        } else {
-               salsa20.XORKeyStream(enc, enc, state.rNonce[:], state.dsaPubH)
+               chacha20.XORKeyStream(enc, enc, state.rNonce, state.dsaPubH)
        }
-       data := append(state.rNonce[:], enc...)
-       data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[:])...)
+       data := append(state.rNonce[8:], enc...)
+       data = append(data, idTag(state.Conf.Id, state.Conf.TimeSync, state.rNonce[8:])...)
        state.conn.Write(data)
        return state
 }
@@ -188,15 +188,15 @@ func (h *Handshake) Server(data []byte) *Peer {
        // R + ENC(H(DSAPub), R, El(CDHPub)) + IDtag
        if h.rNonce == nil && ((!h.Conf.Encless && len(data) >= 48) ||
                (h.Conf.Encless && len(data) == EnclessEnlargeSize+h.Conf.MTU)) {
-               h.rNonce = new([RSize]byte)
-               copy(h.rNonce[:], data[:RSize])
+               h.rNonce = new([16]byte)
+               copy(h.rNonce[8:], data[:RSize])
 
                // Decrypt remote public key
                cDHRepr := new([32]byte)
                if h.Conf.Encless {
                        out, err := EnclessDecode(
                                h.dsaPubH,
-                               h.rNonce[:],
+                               h.rNonce,
                                data[RSize:len(data)-8],
                        )
                        if err != nil {
@@ -205,7 +205,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                        }
                        copy(cDHRepr[:], out)
                } else {
-                       salsa20.XORKeyStream(cDHRepr[:], data[RSize:RSize+32], h.rNonce[:], h.dsaPubH)
+                       chacha20.XORKeyStream(cDHRepr[:], data[RSize:RSize+32], h.rNonce, h.dsaPubH)
                }
 
                // Generate DH keypair
@@ -228,7 +228,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                        }
                } else {
                        encPub = make([]byte, 32)
-                       salsa20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)
+                       chacha20.XORKeyStream(encPub, dhPubRepr[:], h.rNonceNext(1), h.dsaPubH)
                }
 
                // Generate R* and encrypt them
@@ -250,12 +250,12 @@ func (h *Handshake) Server(data []byte) *Peer {
                }
                copy(encRs, append(h.rServer[:], h.sServer[:]...))
                if h.Conf.Encless {
-                       encRs, err = EnclessEncode(h.key, h.rNonce[:], encRs)
+                       encRs, err = EnclessEncode(h.key, h.rNonce, encRs)
                        if err != nil {
                                panic(err)
                        }
                } else {
-                       salsa20.XORKeyStream(encRs, encRs, h.rNonce[:], h.key)
+                       chacha20.XORKeyStream(encRs, encRs, h.rNonce, h.key)
                }
 
                // Send that to client
@@ -282,7 +282,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                        dec = dec[:RSize+RSize+SSize+ed25519.SignatureSize]
                } else {
                        dec = make([]byte, RSize+RSize+SSize+ed25519.SignatureSize)
-                       salsa20.XORKeyStream(
+                       chacha20.XORKeyStream(
                                dec,
                                data[:RSize+RSize+SSize+ed25519.SignatureSize],
                                h.rNonceNext(1),
@@ -314,7 +314,7 @@ func (h *Handshake) Server(data []byte) *Peer {
                                panic(err)
                        }
                } else {
-                       salsa20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
+                       chacha20.XORKeyStream(enc, enc, h.rNonceNext(2), h.key)
                }
                h.conn.Write(append(enc, idTag(h.Conf.Id, h.Conf.TimeSync, enc)...))
 
@@ -359,7 +359,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                        }
                        copy(sDHRepr[:], tmp[:32])
                } else {
-                       salsa20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH)
+                       chacha20.XORKeyStream(sDHRepr[:], data[:32], h.rNonceNext(1), h.dsaPubH)
                }
 
                // Compute shared key
@@ -371,11 +371,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                h.rServer = new([RSize]byte)
                h.sServer = new([SSize]byte)
                if h.Conf.Encless {
-                       tmp, err = EnclessDecode(
-                               h.key,
-                               h.rNonce[:],
-                               data[len(data)/2:len(data)-8],
-                       )
+                       tmp, err = EnclessDecode(h.key, h.rNonce, data[len(data)/2:len(data)-8])
                        if err != nil {
                                log.Println("Unable to decode packet from", h.addr, err)
                                return nil
@@ -384,7 +380,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                        copy(h.sServer[:], tmp[RSize:RSize+SSize])
                } else {
                        decRs := make([]byte, RSize+SSize)
-                       salsa20.XORKeyStream(decRs, data[SSize:SSize+RSize+SSize], h.rNonce[:], h.key)
+                       chacha20.XORKeyStream(decRs, data[SSize:SSize+RSize+SSize], h.rNonce, h.key)
                        copy(h.rServer[:], decRs[:RSize])
                        copy(h.sServer[:], decRs[RSize:])
                }
@@ -416,7 +412,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                                panic(err)
                        }
                } else {
-                       salsa20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)
+                       chacha20.XORKeyStream(enc, enc, h.rNonceNext(1), h.key)
                }
 
                // Send that to server
@@ -438,7 +434,7 @@ func (h *Handshake) Client(data []byte) *Peer {
                        dec = dec[:RSize]
                } else {
                        dec = make([]byte, RSize)
-                       salsa20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
+                       chacha20.XORKeyStream(dec, data[:RSize], h.rNonceNext(2), h.key)
                }
                if subtle.ConstantTimeCompare(dec, h.rClient[:]) != 1 {
                        log.Println("Invalid client's random number with", h.addr)
index 213e8174786df4db45d72abfa40a20043851b9a4..22c893c80fb51d3bb0bb1affbfa395e32a137257 100644 (file)
@@ -28,16 +28,16 @@ import (
        "sync/atomic"
        "time"
 
+       "chacha20"
        "golang.org/x/crypto/blake2b"
        "golang.org/x/crypto/poly1305"
-       "golang.org/x/crypto/salsa20"
 )
 
 const (
        NonceSize       = 8
        NonceBucketSize = 256
        TagSize         = poly1305.TagSize
-       // S20BS is Salsa20's internal blocksize in bytes
+       // S20BS is ChaCha20's internal blocksize in bytes
        S20BS = 64
        // Maximal amount of bytes transfered with single key (4 GiB)
        MaxBytesPerKey uint64 = 1 << 32
@@ -51,7 +51,7 @@ const (
 
 func newNonces(key *[32]byte, i uint64) chan *[NonceSize]byte {
        macKey := make([]byte, 32)
-       salsa20.XORKeyStream(macKey, make([]byte, 32), make([]byte, 8), key)
+       chacha20.XORKeyStream(macKey, make([]byte, 32), new([16]byte), key)
        mac, err := blake2b.New256(macKey)
        if err != nil {
                panic(err)
@@ -108,6 +108,7 @@ type Peer struct {
        bufR     []byte
        tagR     *[TagSize]byte
        keyAuthR *[SSize]byte
+       nonceR   *[16]byte
        pktSizeR int
 
        // UDP-related
@@ -126,6 +127,7 @@ type Peer struct {
        bufT     []byte
        tagT     *[TagSize]byte
        keyAuthT *[SSize]byte
+       nonceT   *[16]byte
        frameT   []byte
        noncesT  chan *[NonceSize]byte
 }
@@ -201,7 +203,9 @@ func newPeer(isClient bool, addr string, conn io.Writer, conf *PeerConf, key *[S
                tagR:     new([TagSize]byte),
                tagT:     new([TagSize]byte),
                keyAuthR: new([SSize]byte),
+               nonceR:   new([16]byte),
                keyAuthT: new([SSize]byte),
+               nonceT:   new([16]byte),
        }
 
        if isClient {
@@ -271,22 +275,19 @@ func (p *Peer) EthProcess(data []byte) {
        }
        copy(p.frameT[len(p.frameT)-NonceSize:], (<-p.noncesT)[:])
        var out []byte
+       copy(p.nonceT[8:], p.frameT[len(p.frameT)-NonceSize:])
        if p.Encless {
                var err error
-               out, err = EnclessEncode(
-                       p.key,
-                       p.frameT[len(p.frameT)-NonceSize:],
-                       p.frameT[:len(p.frameT)-NonceSize],
-               )
+               out, err = EnclessEncode(p.key, p.nonceT, p.frameT[:len(p.frameT)-NonceSize])
                if err != nil {
                        panic(err)
                }
                out = append(out, p.frameT[len(p.frameT)-NonceSize:]...)
        } else {
-               salsa20.XORKeyStream(
+               chacha20.XORKeyStream(
                        p.bufT[:S20BS+len(p.frameT)-NonceSize],
                        p.bufT[:S20BS+len(p.frameT)-NonceSize],
-                       p.frameT[len(p.frameT)-NonceSize:],
+                       p.nonceT,
                        p.key,
                )
                copy(p.keyAuthT[:], p.bufT[:SSize])
@@ -308,13 +309,10 @@ func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
        }
        var out []byte
        p.BusyR.Lock()
+       copy(p.nonceR[8:], data[len(data)-NonceSize:])
        if p.Encless {
                var err error
-               out, err = EnclessDecode(
-                       p.key,
-                       data[len(data)-NonceSize:],
-                       data[:len(data)-NonceSize],
-               )
+               out, err = EnclessDecode(p.key, p.nonceR, data[:len(data)-NonceSize])
                if err != nil {
                        p.FramesUnauth++
                        p.BusyR.Unlock()
@@ -325,10 +323,10 @@ func (p *Peer) PktProcess(data []byte, tap io.Writer, reorderable bool) bool {
                        p.bufR[i] = 0
                }
                copy(p.bufR[S20BS:], data[TagSize:])
-               salsa20.XORKeyStream(
+               chacha20.XORKeyStream(
                        p.bufR[:S20BS+len(data)-TagSize-NonceSize],
                        p.bufR[:S20BS+len(data)-TagSize-NonceSize],
-                       data[len(data)-NonceSize:],
+                       p.nonceR,
                        p.key,
                )
                copy(p.keyAuthR[:], p.bufR[:SSize])
index 8a494f982dddc6f3e7b69111bc9219c1ac30752b..7be321b344336bb77ad88a8c9165799214a4ecde 100755 (executable)
@@ -27,9 +27,9 @@ golang.org/x/crypto/LICENSE
 golang.org/x/crypto/PATENTS
 golang.org/x/crypto/README
 golang.org/x/crypto/blake2b
+golang.org/x/crypto/chacha20poly1305
 golang.org/x/crypto/curve25519
 golang.org/x/crypto/poly1305
-golang.org/x/crypto/salsa20
 golang.org/x/crypto/ssh/terminal
 EOF
 tar cfCI - src $tmp/includes | tar xfC - $tmp