mirror of https://github.com/cbeuw/Cloak
Explicitly allow buf overlap in obfs
This commit is contained in:
parent
97eb6aa096
commit
53c0c6bafe
|
|
@ -9,10 +9,9 @@ import (
|
||||||
"github.com/cbeuw/Cloak/internal/util"
|
"github.com/cbeuw/Cloak/internal/util"
|
||||||
"golang.org/x/crypto/chacha20poly1305"
|
"golang.org/x/crypto/chacha20poly1305"
|
||||||
"golang.org/x/crypto/salsa20"
|
"golang.org/x/crypto/salsa20"
|
||||||
"io"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Obfser func(*Frame, []byte) (int, error)
|
type Obfser func(*Frame, []byte, int) (int, error)
|
||||||
type Deobfser func([]byte) (*Frame, error)
|
type Deobfser func([]byte) (*Frame, error)
|
||||||
|
|
||||||
var u32 = binary.BigEndian.Uint32
|
var u32 = binary.BigEndian.Uint32
|
||||||
|
|
@ -39,13 +38,17 @@ type Obfuscator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func MakeObfs(salsaKey [32]byte, payloadCipher cipher.AEAD) Obfser {
|
func MakeObfs(salsaKey [32]byte, payloadCipher cipher.AEAD) Obfser {
|
||||||
obfs := func(f *Frame, buf []byte) (int, error) {
|
obfs := func(f *Frame, buf []byte, payloadOffsetInBuf int) (int, error) {
|
||||||
// we need the encrypted data to be at least 8 bytes to be used as nonce for salsa20 stream header encryption
|
// we need the encrypted data to be at least 8 bytes to be used as nonce for salsa20 stream header encryption
|
||||||
// this will be the case if the encryption method is an AEAD cipher, however for plain, it's well possible
|
// this will be the case if the encryption method is an AEAD cipher, however for plain, it's well possible
|
||||||
// that the frame payload is smaller than 8 bytes, so we need to add on the difference
|
// that the frame payload is smaller than 8 bytes, so we need to add on the difference
|
||||||
|
payloadLen := len(f.Payload)
|
||||||
|
if payloadLen == 0 {
|
||||||
|
return 0, errors.New("payload cannot be empty")
|
||||||
|
}
|
||||||
var extraLen int
|
var extraLen int
|
||||||
if payloadCipher == nil {
|
if payloadCipher == nil {
|
||||||
if extraLen = 8 - len(f.Payload); extraLen < 0 {
|
if extraLen = 8 - payloadLen; extraLen < 0 {
|
||||||
extraLen = 0
|
extraLen = 0
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -54,31 +57,34 @@ func MakeObfs(salsaKey [32]byte, payloadCipher cipher.AEAD) Obfser {
|
||||||
return 0, errors.New("AEAD's Overhead cannot be fewer than 8 bytes")
|
return 0, errors.New("AEAD's Overhead cannot be fewer than 8 bytes")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// usefulLen is the amount of bytes that will be eventually sent off
|
|
||||||
usefulLen := HEADER_LEN + len(f.Payload) + extraLen
|
usefulLen := HEADER_LEN + payloadLen + extraLen
|
||||||
if usefulLen < HEADER_LEN || len(buf) < usefulLen { // compiler hint to eliminate bound check
|
if len(buf) < usefulLen {
|
||||||
return 0, io.ErrShortBuffer
|
return 0, errors.New("obfs buffer too small")
|
||||||
}
|
}
|
||||||
// we do as much in-place as possible to save allocation
|
// we do as much in-place as possible to save allocation
|
||||||
header := buf[:HEADER_LEN]
|
payload := buf[HEADER_LEN : HEADER_LEN+payloadLen]
|
||||||
encryptedPayloadWithExtra := buf[HEADER_LEN:usefulLen]
|
if payloadOffsetInBuf != HEADER_LEN {
|
||||||
|
// if payload is not at the correct location in buffer
|
||||||
|
copy(payload, f.Payload)
|
||||||
|
}
|
||||||
|
|
||||||
|
header := buf[:HEADER_LEN]
|
||||||
putU32(header[0:4], f.StreamID)
|
putU32(header[0:4], f.StreamID)
|
||||||
putU64(header[4:12], f.Seq)
|
putU64(header[4:12], f.Seq)
|
||||||
header[12] = f.Closing
|
header[12] = f.Closing
|
||||||
header[13] = byte(extraLen)
|
header[13] = byte(extraLen)
|
||||||
|
|
||||||
if payloadCipher == nil {
|
if payloadCipher == nil {
|
||||||
copy(encryptedPayloadWithExtra, f.Payload)
|
|
||||||
if extraLen != 0 { // read nonce
|
if extraLen != 0 { // read nonce
|
||||||
util.CryptoRandRead(encryptedPayloadWithExtra[len(encryptedPayloadWithExtra)-extraLen:])
|
extra := buf[usefulLen-extraLen : usefulLen]
|
||||||
|
util.CryptoRandRead(extra)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ciphertext := payloadCipher.Seal(nil, header[:12], f.Payload, nil)
|
payloadCipher.Seal(payload[:0], header[:12], payload, nil)
|
||||||
copy(encryptedPayloadWithExtra, ciphertext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nonce := encryptedPayloadWithExtra[len(encryptedPayloadWithExtra)-8:]
|
nonce := buf[usefulLen-8 : usefulLen]
|
||||||
salsa20.XORKeyStream(header, header, nonce, &salsaKey)
|
salsa20.XORKeyStream(header, header, nonce, &salsaKey)
|
||||||
|
|
||||||
return usefulLen, nil
|
return usefulLen, nil
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ func TestGenerateObfs(t *testing.T) {
|
||||||
f := &Frame{}
|
f := &Frame{}
|
||||||
_testFrame, _ := quick.Value(reflect.TypeOf(f), rand.New(rand.NewSource(42)))
|
_testFrame, _ := quick.Value(reflect.TypeOf(f), rand.New(rand.NewSource(42)))
|
||||||
testFrame := _testFrame.Interface().(*Frame)
|
testFrame := _testFrame.Interface().(*Frame)
|
||||||
i, err := obfuscator.Obfs(testFrame, obfsBuf)
|
i, err := obfuscator.Obfs(testFrame, obfsBuf, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ct.Error("failed to obfs ", err)
|
ct.Error("failed to obfs ", err)
|
||||||
return
|
return
|
||||||
|
|
@ -92,7 +92,7 @@ func BenchmarkObfs(b *testing.B) {
|
||||||
b.SetBytes(int64(len(testFrame.Payload)))
|
b.SetBytes(int64(len(testFrame.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
obfs(testFrame, obfsBuf)
|
obfs(testFrame, obfsBuf, 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
b.Run("AES128GCM", func(b *testing.B) {
|
b.Run("AES128GCM", func(b *testing.B) {
|
||||||
|
|
@ -103,7 +103,7 @@ func BenchmarkObfs(b *testing.B) {
|
||||||
b.SetBytes(int64(len(testFrame.Payload)))
|
b.SetBytes(int64(len(testFrame.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
obfs(testFrame, obfsBuf)
|
obfs(testFrame, obfsBuf, 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
b.Run("plain", func(b *testing.B) {
|
b.Run("plain", func(b *testing.B) {
|
||||||
|
|
@ -111,7 +111,7 @@ func BenchmarkObfs(b *testing.B) {
|
||||||
b.SetBytes(int64(len(testFrame.Payload)))
|
b.SetBytes(int64(len(testFrame.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
obfs(testFrame, obfsBuf)
|
obfs(testFrame, obfsBuf, 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
b.Run("chacha20Poly1305", func(b *testing.B) {
|
b.Run("chacha20Poly1305", func(b *testing.B) {
|
||||||
|
|
@ -121,7 +121,7 @@ func BenchmarkObfs(b *testing.B) {
|
||||||
b.SetBytes(int64(len(testFrame.Payload)))
|
b.SetBytes(int64(len(testFrame.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
obfs(testFrame, obfsBuf)
|
obfs(testFrame, obfsBuf, 0)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -145,7 +145,7 @@ func BenchmarkDeobfs(b *testing.B) {
|
||||||
payloadCipher, _ := cipher.NewGCM(c)
|
payloadCipher, _ := cipher.NewGCM(c)
|
||||||
|
|
||||||
obfs := MakeObfs(key, payloadCipher)
|
obfs := MakeObfs(key, payloadCipher)
|
||||||
n, _ := obfs(testFrame, obfsBuf)
|
n, _ := obfs(testFrame, obfsBuf, 0)
|
||||||
deobfs := MakeDeobfs(key, payloadCipher)
|
deobfs := MakeDeobfs(key, payloadCipher)
|
||||||
|
|
||||||
b.SetBytes(int64(n))
|
b.SetBytes(int64(n))
|
||||||
|
|
@ -159,7 +159,7 @@ func BenchmarkDeobfs(b *testing.B) {
|
||||||
payloadCipher, _ := cipher.NewGCM(c)
|
payloadCipher, _ := cipher.NewGCM(c)
|
||||||
|
|
||||||
obfs := MakeObfs(key, payloadCipher)
|
obfs := MakeObfs(key, payloadCipher)
|
||||||
n, _ := obfs(testFrame, obfsBuf)
|
n, _ := obfs(testFrame, obfsBuf, 0)
|
||||||
deobfs := MakeDeobfs(key, payloadCipher)
|
deobfs := MakeDeobfs(key, payloadCipher)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -170,7 +170,7 @@ func BenchmarkDeobfs(b *testing.B) {
|
||||||
})
|
})
|
||||||
b.Run("plain", func(b *testing.B) {
|
b.Run("plain", func(b *testing.B) {
|
||||||
obfs := MakeObfs(key, nil)
|
obfs := MakeObfs(key, nil)
|
||||||
n, _ := obfs(testFrame, obfsBuf)
|
n, _ := obfs(testFrame, obfsBuf, 0)
|
||||||
deobfs := MakeDeobfs(key, nil)
|
deobfs := MakeDeobfs(key, nil)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -183,7 +183,7 @@ func BenchmarkDeobfs(b *testing.B) {
|
||||||
payloadCipher, _ := chacha20poly1305.New(key[:16])
|
payloadCipher, _ := chacha20poly1305.New(key[:16])
|
||||||
|
|
||||||
obfs := MakeObfs(key, payloadCipher)
|
obfs := MakeObfs(key, payloadCipher)
|
||||||
n, _ := obfs(testFrame, obfsBuf)
|
n, _ := obfs(testFrame, obfsBuf, 0)
|
||||||
deobfs := MakeDeobfs(key, payloadCipher)
|
deobfs := MakeDeobfs(key, payloadCipher)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
|
||||||
|
|
@ -161,7 +161,7 @@ func (sesh *Session) closeStream(s *Stream, active bool) error {
|
||||||
s.nextSendSeq++
|
s.nextSendSeq++
|
||||||
|
|
||||||
obfsBuf := make([]byte, len(padding)+64)
|
obfsBuf := make([]byte, len(padding)+64)
|
||||||
i, err := sesh.Obfs(f, obfsBuf)
|
i, err := sesh.Obfs(f, obfsBuf, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -286,7 +286,7 @@ func (sesh *Session) Close() error {
|
||||||
Payload: pad,
|
Payload: pad,
|
||||||
}
|
}
|
||||||
obfsBuf := make([]byte, len(pad)+64)
|
obfsBuf := make([]byte, len(pad)+64)
|
||||||
i, err := sesh.Obfs(f, obfsBuf)
|
i, err := sesh.Obfs(f, obfsBuf, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func TestRecvDataFromRemote(t *testing.T) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_PLAIN, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_PLAIN, sessionKey)
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -62,7 +62,7 @@ func TestRecvDataFromRemote(t *testing.T) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_AES_GCM, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_AES_GCM, sessionKey)
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -89,7 +89,7 @@ func TestRecvDataFromRemote(t *testing.T) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_CHACHA20_POLY1305, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_CHACHA20_POLY1305, sessionKey)
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -117,7 +117,7 @@ func TestRecvDataFromRemote(t *testing.T) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_PLAIN, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_PLAIN, sessionKey)
|
||||||
seshConfigUnordered.Obfuscator = obfuscator
|
seshConfigUnordered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -163,7 +163,7 @@ func TestRecvDataFromRemote_Closing_InOrder(t *testing.T) {
|
||||||
testPayload,
|
testPayload,
|
||||||
}
|
}
|
||||||
// create stream 1
|
// create stream 1
|
||||||
n, _ := sesh.Obfs(f1, obfsBuf)
|
n, _ := sesh.Obfs(f1, obfsBuf, 0)
|
||||||
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving normal frame for stream 1: %v", err)
|
t.Fatalf("receiving normal frame for stream 1: %v", err)
|
||||||
|
|
@ -183,7 +183,7 @@ func TestRecvDataFromRemote_Closing_InOrder(t *testing.T) {
|
||||||
C_NOOP,
|
C_NOOP,
|
||||||
testPayload,
|
testPayload,
|
||||||
}
|
}
|
||||||
n, _ = sesh.Obfs(f2, obfsBuf)
|
n, _ = sesh.Obfs(f2, obfsBuf, 0)
|
||||||
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving normal frame for stream 2: %v", err)
|
t.Fatalf("receiving normal frame for stream 2: %v", err)
|
||||||
|
|
@ -203,7 +203,7 @@ func TestRecvDataFromRemote_Closing_InOrder(t *testing.T) {
|
||||||
C_STREAM,
|
C_STREAM,
|
||||||
testPayload,
|
testPayload,
|
||||||
}
|
}
|
||||||
n, _ = sesh.Obfs(f1CloseStream, obfsBuf)
|
n, _ = sesh.Obfs(f1CloseStream, obfsBuf, 0)
|
||||||
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving stream closing frame for stream 1: %v", err)
|
t.Fatalf("receiving stream closing frame for stream 1: %v", err)
|
||||||
|
|
@ -230,7 +230,7 @@ func TestRecvDataFromRemote_Closing_InOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// close stream 1 again
|
// close stream 1 again
|
||||||
n, _ = sesh.Obfs(f1CloseStream, obfsBuf)
|
n, _ = sesh.Obfs(f1CloseStream, obfsBuf, 0)
|
||||||
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving stream closing frame for stream 1 %v", err)
|
t.Fatalf("receiving stream closing frame for stream 1 %v", err)
|
||||||
|
|
@ -250,7 +250,7 @@ func TestRecvDataFromRemote_Closing_InOrder(t *testing.T) {
|
||||||
Closing: C_SESSION,
|
Closing: C_SESSION,
|
||||||
Payload: testPayload,
|
Payload: testPayload,
|
||||||
}
|
}
|
||||||
n, _ = sesh.Obfs(fCloseSession, obfsBuf)
|
n, _ = sesh.Obfs(fCloseSession, obfsBuf, 0)
|
||||||
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving session closing frame: %v", err)
|
t.Fatalf("receiving session closing frame: %v", err)
|
||||||
|
|
@ -294,7 +294,7 @@ func TestRecvDataFromRemote_Closing_OutOfOrder(t *testing.T) {
|
||||||
C_STREAM,
|
C_STREAM,
|
||||||
testPayload,
|
testPayload,
|
||||||
}
|
}
|
||||||
n, _ := sesh.Obfs(f1CloseStream, obfsBuf)
|
n, _ := sesh.Obfs(f1CloseStream, obfsBuf, 0)
|
||||||
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
err := sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving out of order stream closing frame for stream 1: %v", err)
|
t.Fatalf("receiving out of order stream closing frame for stream 1: %v", err)
|
||||||
|
|
@ -314,7 +314,7 @@ func TestRecvDataFromRemote_Closing_OutOfOrder(t *testing.T) {
|
||||||
C_NOOP,
|
C_NOOP,
|
||||||
testPayload,
|
testPayload,
|
||||||
}
|
}
|
||||||
n, _ = sesh.Obfs(f1, obfsBuf)
|
n, _ = sesh.Obfs(f1, obfsBuf, 0)
|
||||||
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
err = sesh.recvDataFromRemote(obfsBuf[:n])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("receiving normal frame for stream 1: %v", err)
|
t.Fatalf("receiving normal frame for stream 1: %v", err)
|
||||||
|
|
@ -375,7 +375,7 @@ func TestParallel(t *testing.T) {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(frame *Frame) {
|
go func(frame *Frame) {
|
||||||
data := make([]byte, 1000)
|
data := make([]byte, 1000)
|
||||||
n, _ := sesh.Obfs(frame, data)
|
n, _ := sesh.Obfs(frame, data, 0)
|
||||||
data = data[0:n]
|
data = data[0:n]
|
||||||
|
|
||||||
err := sesh.recvDataFromRemote(data)
|
err := sesh.recvDataFromRemote(data)
|
||||||
|
|
@ -463,7 +463,7 @@ func BenchmarkRecvDataFromRemote_Ordered(b *testing.B) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_PLAIN, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_PLAIN, sessionKey)
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
b.SetBytes(int64(len(f.Payload)))
|
b.SetBytes(int64(len(f.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -476,7 +476,7 @@ func BenchmarkRecvDataFromRemote_Ordered(b *testing.B) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_AES_GCM, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_AES_GCM, sessionKey)
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
b.SetBytes(int64(len(f.Payload)))
|
b.SetBytes(int64(len(f.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
@ -489,7 +489,7 @@ func BenchmarkRecvDataFromRemote_Ordered(b *testing.B) {
|
||||||
obfuscator, _ := MakeObfuscator(E_METHOD_CHACHA20_POLY1305, sessionKey)
|
obfuscator, _ := MakeObfuscator(E_METHOD_CHACHA20_POLY1305, sessionKey)
|
||||||
seshConfigOrdered.Obfuscator = obfuscator
|
seshConfigOrdered.Obfuscator = obfuscator
|
||||||
sesh := MakeSession(0, seshConfigOrdered)
|
sesh := MakeSession(0, seshConfigOrdered)
|
||||||
n, _ := sesh.Obfs(f, obfsBuf)
|
n, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
|
|
||||||
b.SetBytes(int64(len(f.Payload)))
|
b.SetBytes(int64(len(f.Payload)))
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
|
||||||
|
|
@ -90,9 +90,9 @@ func (s *Stream) WriteTo(w io.Writer) (int64, error) {
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) sendFrame(f *Frame) error {
|
func (s *Stream) sendFrame(f *Frame, framePayloadOffset int) error {
|
||||||
var cipherTextLen int
|
var cipherTextLen int
|
||||||
cipherTextLen, err := s.session.Obfs(f, s.obfsBuf)
|
cipherTextLen, err := s.session.Obfs(f, s.obfsBuf, framePayloadOffset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +138,7 @@ func (s *Stream) Write(in []byte) (n int, err error) {
|
||||||
Payload: framePayload,
|
Payload: framePayload,
|
||||||
}
|
}
|
||||||
s.nextSendSeq++
|
s.nextSendSeq++
|
||||||
err = s.sendFrame(f)
|
err = s.sendFrame(f, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -168,7 +168,7 @@ func (s *Stream) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
Payload: s.obfsBuf[HEADER_LEN : HEADER_LEN+read],
|
Payload: s.obfsBuf[HEADER_LEN : HEADER_LEN+read],
|
||||||
}
|
}
|
||||||
s.nextSendSeq++
|
s.nextSendSeq++
|
||||||
err = s.sendFrame(f)
|
err = s.sendFrame(f, HEADER_LEN)
|
||||||
s.writingM.Unlock()
|
s.writingM.Unlock()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ import (
|
||||||
|
|
||||||
const payloadLen = 1000
|
const payloadLen = 1000
|
||||||
|
|
||||||
func setupSesh(unordered bool, key [32]byte) *Session {
|
func setupSesh(unordered bool, key [32]byte, encryptionMethod byte) *Session {
|
||||||
obfuscator, _ := MakeObfuscator(0x00, key)
|
obfuscator, _ := MakeObfuscator(encryptionMethod, key)
|
||||||
|
|
||||||
seshConfig := SessionConfig{
|
seshConfig := SessionConfig{
|
||||||
Obfuscator: obfuscator,
|
Obfuscator: obfuscator,
|
||||||
|
|
@ -28,17 +28,28 @@ func BenchmarkStream_Write_Ordered(b *testing.B) {
|
||||||
hole := connutil.Discard()
|
hole := connutil.Discard()
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
sesh := setupSesh(false, sessionKey)
|
|
||||||
sesh.AddConnection(hole)
|
|
||||||
testData := make([]byte, payloadLen)
|
|
||||||
rand.Read(testData)
|
|
||||||
|
|
||||||
|
const testDataLen = 65536
|
||||||
|
testData := make([]byte, testDataLen)
|
||||||
|
rand.Read(testData)
|
||||||
|
eMethods := map[string]byte{
|
||||||
|
"plain": E_METHOD_PLAIN,
|
||||||
|
"chacha20-poly1305": E_METHOD_CHACHA20_POLY1305,
|
||||||
|
"aes-gcm": E_METHOD_AES_GCM,
|
||||||
|
}
|
||||||
|
|
||||||
|
for name, method := range eMethods {
|
||||||
|
b.Run(name, func(b *testing.B) {
|
||||||
|
sesh := setupSesh(false, sessionKey, method)
|
||||||
|
sesh.AddConnection(hole)
|
||||||
stream, _ := sesh.OpenStream()
|
stream, _ := sesh.OpenStream()
|
||||||
b.SetBytes(payloadLen)
|
b.SetBytes(testDataLen)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
stream.Write(testData)
|
stream.Write(testData)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -96,7 +107,7 @@ func TestStream_Write(t *testing.T) {
|
||||||
hole := connutil.Discard()
|
hole := connutil.Discard()
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
sesh := setupSesh(false, sessionKey)
|
sesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
sesh.AddConnection(hole)
|
sesh.AddConnection(hole)
|
||||||
testData := make([]byte, payloadLen)
|
testData := make([]byte, payloadLen)
|
||||||
rand.Read(testData)
|
rand.Read(testData)
|
||||||
|
|
@ -115,8 +126,8 @@ func TestStream_WriteSync(t *testing.T) {
|
||||||
// Close calls made after write MUST have a higher seq
|
// Close calls made after write MUST have a higher seq
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
clientSesh := setupSesh(false, sessionKey)
|
clientSesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
serverSesh := setupSesh(false, sessionKey)
|
serverSesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
w, r := connutil.AsyncPipe()
|
w, r := connutil.AsyncPipe()
|
||||||
clientSesh.AddConnection(&common.TLSConn{Conn: w})
|
clientSesh.AddConnection(&common.TLSConn{Conn: w})
|
||||||
serverSesh.AddConnection(&common.TLSConn{Conn: r})
|
serverSesh.AddConnection(&common.TLSConn{Conn: r})
|
||||||
|
|
@ -161,7 +172,7 @@ func TestStream_WriteSync(t *testing.T) {
|
||||||
func TestStream_Close(t *testing.T) {
|
func TestStream_Close(t *testing.T) {
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
sesh := setupSesh(false, sessionKey)
|
sesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
testPayload := []byte{42, 42, 42}
|
testPayload := []byte{42, 42, 42}
|
||||||
|
|
||||||
f := &Frame{
|
f := &Frame{
|
||||||
|
|
@ -174,7 +185,7 @@ func TestStream_Close(t *testing.T) {
|
||||||
conn, writingEnd := connutil.AsyncPipe()
|
conn, writingEnd := connutil.AsyncPipe()
|
||||||
sesh.AddConnection(conn)
|
sesh.AddConnection(conn)
|
||||||
obfsBuf := make([]byte, 512)
|
obfsBuf := make([]byte, 512)
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
stream, err := sesh.Accept()
|
stream, err := sesh.Accept()
|
||||||
|
|
@ -206,7 +217,7 @@ func TestStream_Close(t *testing.T) {
|
||||||
func TestStream_Read(t *testing.T) {
|
func TestStream_Read(t *testing.T) {
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
sesh := setupSesh(false, sessionKey)
|
sesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
testPayload := []byte{42, 42, 42}
|
testPayload := []byte{42, 42, 42}
|
||||||
const smallPayloadLen = 3
|
const smallPayloadLen = 3
|
||||||
|
|
||||||
|
|
@ -226,7 +237,7 @@ func TestStream_Read(t *testing.T) {
|
||||||
obfsBuf := make([]byte, 512)
|
obfsBuf := make([]byte, 512)
|
||||||
t.Run("Plain read", func(t *testing.T) {
|
t.Run("Plain read", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -252,7 +263,7 @@ func TestStream_Read(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Nil buf", func(t *testing.T) {
|
t.Run("Nil buf", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -265,7 +276,7 @@ func TestStream_Read(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Read after stream close", func(t *testing.T) {
|
t.Run("Read after stream close", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -290,7 +301,7 @@ func TestStream_Read(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Read after session close", func(t *testing.T) {
|
t.Run("Read after session close", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -319,7 +330,7 @@ func TestStream_Read(t *testing.T) {
|
||||||
func TestStream_UnorderedRead(t *testing.T) {
|
func TestStream_UnorderedRead(t *testing.T) {
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
sesh := setupSesh(false, sessionKey)
|
sesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
testPayload := []byte{42, 42, 42}
|
testPayload := []byte{42, 42, 42}
|
||||||
const smallPayloadLen = 3
|
const smallPayloadLen = 3
|
||||||
|
|
||||||
|
|
@ -339,7 +350,7 @@ func TestStream_UnorderedRead(t *testing.T) {
|
||||||
obfsBuf := make([]byte, 512)
|
obfsBuf := make([]byte, 512)
|
||||||
t.Run("Plain read", func(t *testing.T) {
|
t.Run("Plain read", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -361,7 +372,7 @@ func TestStream_UnorderedRead(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Nil buf", func(t *testing.T) {
|
t.Run("Nil buf", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -374,7 +385,7 @@ func TestStream_UnorderedRead(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Read after stream close", func(t *testing.T) {
|
t.Run("Read after stream close", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
@ -399,7 +410,7 @@ func TestStream_UnorderedRead(t *testing.T) {
|
||||||
})
|
})
|
||||||
t.Run("Read after session close", func(t *testing.T) {
|
t.Run("Read after session close", func(t *testing.T) {
|
||||||
f.StreamID = streamID
|
f.StreamID = streamID
|
||||||
i, _ := sesh.Obfs(f, obfsBuf)
|
i, _ := sesh.Obfs(f, obfsBuf, 0)
|
||||||
streamID++
|
streamID++
|
||||||
writingEnd.Write(obfsBuf[:i])
|
writingEnd.Write(obfsBuf[:i])
|
||||||
time.Sleep(100 * time.Microsecond)
|
time.Sleep(100 * time.Microsecond)
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ func TestSwitchboard_TxCredit(t *testing.T) {
|
||||||
func TestSwitchboard_CloseOnOneDisconn(t *testing.T) {
|
func TestSwitchboard_CloseOnOneDisconn(t *testing.T) {
|
||||||
var sessionKey [32]byte
|
var sessionKey [32]byte
|
||||||
rand.Read(sessionKey[:])
|
rand.Read(sessionKey[:])
|
||||||
sesh := setupSesh(false, sessionKey)
|
sesh := setupSesh(false, sessionKey, E_METHOD_PLAIN)
|
||||||
|
|
||||||
conn0client, conn0server := connutil.AsyncPipe()
|
conn0client, conn0server := connutil.AsyncPipe()
|
||||||
sesh.AddConnection(conn0client)
|
sesh.AddConnection(conn0client)
|
||||||
|
|
|
||||||
|
|
@ -381,7 +381,7 @@ func BenchmarkThroughput(b *testing.B) {
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Run("single conn", func(b *testing.B) {
|
b.Run("single conn", func(b *testing.B) {
|
||||||
more := make(chan int, 100)
|
more := make(chan int, 10)
|
||||||
go func() {
|
go func() {
|
||||||
writeBuf := make([]byte, bufSize+100)
|
writeBuf := make([]byte, bufSize+100)
|
||||||
serverConn, _ := pxyServerL.Accept()
|
serverConn, _ := pxyServerL.Accept()
|
||||||
|
|
@ -396,45 +396,37 @@ func BenchmarkThroughput(b *testing.B) {
|
||||||
b.SetBytes(bufSize)
|
b.SetBytes(bufSize)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
clientConn.Read(readBuf)
|
io.ReadFull(clientConn, readBuf)
|
||||||
more <- 0
|
more <- 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
b.Run("multiconn", func(b *testing.B) {
|
b.Run("multiconn", func(b *testing.B) {
|
||||||
var connsIds sync.Pool
|
writeBuf := make([]byte, bufSize)
|
||||||
conns := make([]net.Conn, numConns)
|
b.SetBytes(bufSize)
|
||||||
more := make([]chan int, numConns)
|
b.ResetTimer()
|
||||||
for i := 0; i < numConns; i++ {
|
b.RunParallel(func(pb *testing.PB) {
|
||||||
conns[i], _ = pxyClientD.Dial("", "")
|
ready := make(chan int, 10)
|
||||||
conns[i].Write([]byte{1}) // to make server accept
|
|
||||||
connsIds.Put(i)
|
|
||||||
moreChan := make(chan int, 100)
|
|
||||||
more[i] = moreChan
|
|
||||||
writeBuf := make([]byte, bufSize + 100)
|
|
||||||
go func() {
|
go func() {
|
||||||
serverConn, _ := pxyServerL.Accept()
|
serverConn, _ := pxyServerL.Accept()
|
||||||
for {
|
for {
|
||||||
serverConn.Write(writeBuf)
|
serverConn.Write(writeBuf)
|
||||||
<- moreChan
|
<-ready
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
readBuf := make([]byte, bufSize)
|
||||||
b.SetParallelism(numConns)
|
clientConn, _ := pxyClientD.Dial("", "")
|
||||||
b.ResetTimer()
|
clientConn.Write([]byte{1}) // to make server accept
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
buf := make([]byte, bufSize)
|
|
||||||
connNum := connsIds.Get().(int)
|
|
||||||
for pb.Next() {
|
for pb.Next() {
|
||||||
n, _ := conns[connNum].Read(buf)
|
io.ReadFull(clientConn,readBuf)
|
||||||
more[connNum] <- 0
|
ready <- 0
|
||||||
b.SetBytes(int64(n))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue