From 625364835690bd52db69bd5a574db1f432ad5310 Mon Sep 17 00:00:00 2001 From: 9seconds Date: Sun, 1 Jul 2018 12:01:56 +0300 Subject: [PATCH] Remove frame pool for obfuscated2 frames --- client/direct.go | 1 - obfuscated2/frame.go | 32 +++++++++++++++----------------- obfuscated2/frame_pool.go | 24 ------------------------ obfuscated2/frame_test.go | 8 ++++---- obfuscated2/obfuscated2.go | 18 ++++++++---------- obfuscated2/obfuscated2_test.go | 10 +++++----- telegram/direct.go | 3 +-- 7 files changed, 33 insertions(+), 63 deletions(-) delete mode 100644 obfuscated2/frame_pool.go diff --git a/client/direct.go b/client/direct.go index f4db89c..ed40dbe 100644 --- a/client/direct.go +++ b/client/direct.go @@ -29,7 +29,6 @@ func DirectInit(conn net.Conn, conf *config.Config) (*mtproto.ConnectionOpts, io if err != nil { return nil, nil, errors.Annotate(err, "Cannot extract frame") } - defer obfuscated2.ReturnFrame(frame) obfs2, connOpts, err := obfuscated2.ParseObfuscated2ClientFrame(conf.Secret, frame) if err != nil { diff --git a/obfuscated2/frame.go b/obfuscated2/frame.go index ea03241..6c6f6ab 100644 --- a/obfuscated2/frame.go +++ b/obfuscated2/frame.go @@ -66,57 +66,55 @@ func (f Frame) ConnectionType() (mtproto.ConnectionType, error) { // Invert inverts frame for extracting encryption keys. Pkease check that link: // https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/ -func (f Frame) Invert() *Frame { - reversed := MakeFrame() - copy(*reversed, f) +func (f Frame) Invert() Frame { + reversed := make(Frame, FrameLen) + copy(reversed, f) for i := 0; i < frameLenKey+frameLenIV; i++ { - (*reversed)[frameOffsetFirst+i] = f[frameOffsetIV-1-i] + reversed[frameOffsetFirst+i] = f[frameOffsetIV-1-i] } return reversed } // ExtractFrame extracts exact obfuscated2 handshake frame from given reader. -func ExtractFrame(conn io.Reader) (*Frame, error) { - frame := MakeFrame() - buf := bytes.NewBuffer(*frame) +func ExtractFrame(conn io.Reader) (Frame, error) { + frame := make(Frame, FrameLen) + buf := bytes.NewBuffer(frame) buf.Reset() if _, err := io.CopyN(buf, conn, FrameLen); err != nil { - ReturnFrame(frame) return nil, errors.Annotate(err, "Cannot extract obfuscated header") } - copy(*frame, buf.Bytes()) + copy(frame, buf.Bytes()) return frame, nil } -func generateFrame(connectionType mtproto.ConnectionType) *Frame { - frame := MakeFrame() - data := *frame +func generateFrame(connectionType mtproto.ConnectionType) Frame { + frame := make(Frame, FrameLen) for { - if _, err := rand.Read(data); err != nil { + if _, err := rand.Read(frame); err != nil { continue } - if data[0] == 0xef { + if frame[0] == 0xef { continue } - val := (uint32(data[3]) << 24) | (uint32(data[2]) << 16) | (uint32(data[1]) << 8) | uint32(data[0]) + val := (uint32(frame[3]) << 24) | (uint32(frame[2]) << 16) | (uint32(frame[1]) << 8) | uint32(frame[0]) if val == 0x44414548 || val == 0x54534f50 || val == 0x20544547 || val == 0x4954504f || val == 0xeeeeeeee { continue } - val = (uint32(data[7]) << 24) | (uint32(data[6]) << 16) | (uint32(data[5]) << 8) | uint32(data[4]) + val = (uint32(frame[7]) << 24) | (uint32(frame[6]) << 16) | (uint32(frame[5]) << 8) | uint32(frame[4]) if val == 0x00000000 { continue } // error has to be checked before calling this function tag, _ := connectionType.Tag() // nolint: errcheck - copy(data.Magic(), tag) + copy(frame.Magic(), tag) return frame } diff --git a/obfuscated2/frame_pool.go b/obfuscated2/frame_pool.go deleted file mode 100644 index 431073f..0000000 --- a/obfuscated2/frame_pool.go +++ /dev/null @@ -1,24 +0,0 @@ -package obfuscated2 - -import "sync" - -var framePool sync.Pool - -// MakeFrame returns new pointer to the handshake frame. -func MakeFrame() *Frame { - return framePool.Get().(*Frame) -} - -// ReturnFrame returns pointer to the handshake frame back to the pool. -func ReturnFrame(f *Frame) { - framePool.Put(f) -} - -func init() { - framePool = sync.Pool{ - New: func() interface{} { - data := make(Frame, FrameLen) - return &data - }, - } -} diff --git a/obfuscated2/frame_test.go b/obfuscated2/frame_test.go index 0c7e692..42d997c 100644 --- a/obfuscated2/frame_test.go +++ b/obfuscated2/frame_test.go @@ -54,21 +54,21 @@ func TestFrameValid(t *testing.T) { func TestFrameDoubleInvert(t *testing.T) { frame := makeFrame() - assert.True(t, bytes.Equal(frame, *frame.Invert().Invert())) + assert.True(t, bytes.Equal(frame, frame.Invert().Invert())) } func TestFrameInvert(t *testing.T) { frame := makeFrame() reversed := frame.Invert() - assert.Exactly(t, frame[:8], (*reversed)[:8]) - assert.Exactly(t, frame[56:], (*reversed)[56:]) + assert.Exactly(t, frame[:8], reversed[:8]) + assert.Exactly(t, frame[56:], reversed[56:]) toCompare := make([]byte, 48) for i := 0; i < 48; i++ { toCompare[i] = frame[55-i] } - assert.Equal(t, []byte((*reversed)[8:56]), toCompare) + assert.Equal(t, []byte(reversed[8:56]), toCompare) } func TestFrameGenerateValid(t *testing.T) { diff --git a/obfuscated2/obfuscated2.go b/obfuscated2/obfuscated2.go index bc027ad..50a34c7 100644 --- a/obfuscated2/obfuscated2.go +++ b/obfuscated2/obfuscated2.go @@ -21,7 +21,7 @@ type Obfuscated2 struct { // details: http://telegra.ph/telegram-blocks-wtf-05-26 // // Beware, link above is in russian. -func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, *mtproto.ConnectionOpts, error) { +func ParseObfuscated2ClientFrame(secret []byte, frame Frame) (*Obfuscated2, *mtproto.ConnectionOpts, error) { decHasher := sha256.New() decHasher.Write(frame.Key()) // nolint: errcheck decHasher.Write(secret) // nolint: errcheck @@ -33,9 +33,8 @@ func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, *mt encHasher.Write(secret) // nolint: errcheck encryptor := makeStreamCipher(encHasher.Sum(nil), invertedFrame.IV()) - decryptedFrame := MakeFrame() - defer ReturnFrame(decryptedFrame) - decryptor.XORKeyStream(*decryptedFrame, *frame) + decryptedFrame := make(Frame, FrameLen) + decryptor.XORKeyStream(decryptedFrame, frame) connType, err := decryptedFrame.ConnectionType() if err != nil { return nil, nil, errors.Annotate(err, "Unknown protocol") @@ -56,18 +55,17 @@ func ParseObfuscated2ClientFrame(secret []byte, frame *Frame) (*Obfuscated2, *mt // MakeTelegramObfuscated2Frame creates new handshake frame to send to // Telegram. // https://blog.susanka.eu/how-telegram-obfuscates-its-mtproto-traffic/ -func MakeTelegramObfuscated2Frame(opts *mtproto.ConnectionOpts) (*Obfuscated2, *Frame) { +func MakeTelegramObfuscated2Frame(opts *mtproto.ConnectionOpts) (*Obfuscated2, Frame) { frame := generateFrame(opts.ConnectionType) encryptor := makeStreamCipher(frame.Key(), frame.IV()) decryptorFrame := frame.Invert() decryptor := makeStreamCipher(decryptorFrame.Key(), decryptorFrame.IV()) - copyFrame := MakeFrame() - defer ReturnFrame(copyFrame) - copy((*copyFrame)[:frameOffsetIV], (*frame)[:frameOffsetIV]) - encryptor.XORKeyStream(*frame, *frame) - copy((*frame)[:frameOffsetIV], (*copyFrame)[:frameOffsetIV]) + copyFrame := make(Frame, FrameLen) + copy(copyFrame[:frameOffsetIV], frame[:frameOffsetIV]) + encryptor.XORKeyStream(frame, frame) + copy(frame[:frameOffsetIV], copyFrame[:frameOffsetIV]) obfs := &Obfuscated2{ Decryptor: decryptor, diff --git a/obfuscated2/obfuscated2_test.go b/obfuscated2/obfuscated2_test.go index 0c7b1a8..c6b5c4a 100644 --- a/obfuscated2/obfuscated2_test.go +++ b/obfuscated2/obfuscated2_test.go @@ -18,7 +18,7 @@ func TestObfs2TelegramFrameDecrypt(t *testing.T) { decryptor := makeStreamCipher(frame.Key(), frame.IV()) decrypted := make(Frame, FrameLen) - decryptor.XORKeyStream(decrypted, *frame) + decryptor.XORKeyStream(decrypted, frame) _, err := decrypted.ConnectionType() assert.Nil(t, err) @@ -53,8 +53,8 @@ func TestObfs2Full(t *testing.T) { encryptor := makeStreamCipher(clientKey, clientFrame.IV()) encrypted := make(Frame, FrameLen) - encryptor.XORKeyStream(encrypted, *clientFrame) - copy(encrypted[:56], (*clientFrame)[:56]) + encryptor.XORKeyStream(encrypted, clientFrame) + copy(encrypted[:56], clientFrame[:56]) invertedClientFrame := clientFrame.Invert() clientHasher = sha256.New() @@ -63,7 +63,7 @@ func TestObfs2Full(t *testing.T) { invertedClientKey := clientHasher.Sum(nil) clientDecryptor := makeStreamCipher(invertedClientKey, invertedClientFrame.IV()) - clientObfs, _, err := ParseObfuscated2ClientFrame(secret, &encrypted) + clientObfs, _, err := ParseObfuscated2ClientFrame(secret, encrypted) assert.Nil(t, err) connOpts := &mtproto.ConnectionOpts{ @@ -73,7 +73,7 @@ func TestObfs2Full(t *testing.T) { tgObfs, tgFrame := MakeTelegramObfuscated2Frame(connOpts) tgDecryptor := makeStreamCipher(tgFrame.Key(), tgFrame.IV()) decrypted := make(Frame, FrameLen) - tgDecryptor.XORKeyStream(decrypted, *tgFrame) + tgDecryptor.XORKeyStream(decrypted, tgFrame) _, err = decrypted.ConnectionType() assert.Nil(t, err) diff --git a/telegram/direct.go b/telegram/direct.go index f1ee52f..5681415 100644 --- a/telegram/direct.go +++ b/telegram/direct.go @@ -46,9 +46,8 @@ func (t *directTelegram) Dial(connOpts *mtproto.ConnectionOpts) (io.ReadWriteClo func (t *directTelegram) Init(connOpts *mtproto.ConnectionOpts, conn io.ReadWriteCloser) (io.ReadWriteCloser, error) { obfs2, frame := obfuscated2.MakeTelegramObfuscated2Frame(connOpts) - defer obfuscated2.ReturnFrame(frame) - if n, err := conn.Write(*frame); err != nil || n != len(*frame) { + if n, err := conn.Write(frame); err != nil || n != obfuscated2.FrameLen { return nil, errors.Annotate(err, "Cannot write hadnshake frame") }