move gotd fork into repo. (#111)
- update to latest telegram layer - remove some references to fields in tg.Entities that don't exist in the schema - originally added here: https://github.com/beeper/td/commit/820929062a2ba0104397bc01235ab58a9cff780e - referenced here - https://github.com/mautrix/telegramgo/commit/124f0967ed195b5a380c9bd02e170ada9710dde3 - https://github.com/mautrix/telegramgo/commit/4205047aab2e0639217148b5d125bfaab668bd8e
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/bin"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/clock"
|
||||
)
|
||||
|
||||
const clientHelloLength = 517
|
||||
|
||||
func createClientHello(b *bin.Buffer, sessionID [32]byte, domain string, key [32]byte) (randomOffset int) {
|
||||
S := func(s string) {
|
||||
b.Buf = append(b.Buf, s...)
|
||||
}
|
||||
Z := func(n int) {
|
||||
randomOffset = len(b.Buf)
|
||||
b.Expand(n)
|
||||
}
|
||||
G := func(_ int) {
|
||||
b.Expand(0)
|
||||
}
|
||||
R := func() {
|
||||
b.Buf = append(b.Buf, sessionID[:]...)
|
||||
}
|
||||
D := func() {
|
||||
b.Buf = append(b.Buf, domain...)
|
||||
}
|
||||
K := func() {
|
||||
b.Buf = append(b.Buf, key[:]...)
|
||||
}
|
||||
var stack []int
|
||||
Open := func() {
|
||||
stack = append(stack, b.Len())
|
||||
b.Expand(2)
|
||||
}
|
||||
Close := func() {
|
||||
lastIdx := len(stack) - 1
|
||||
s := stack[lastIdx]
|
||||
stack = stack[:lastIdx]
|
||||
|
||||
length := b.Len() - (s + 2)
|
||||
binary.BigEndian.PutUint16(b.Buf[s:], uint16(length))
|
||||
}
|
||||
|
||||
S("\x16\x03\x01\x02\x00\x01\x00\x01\xfc\x03\x03")
|
||||
Z(32)
|
||||
S("\x20")
|
||||
R()
|
||||
S("\x00\x20")
|
||||
G(0)
|
||||
S("\x13\x01\x13\x02\x13\x03\xc0\x2b\xc0\x2f\xc0\x2c\xc0\x30\xcc\xa9" +
|
||||
"\xcc\xa8\xc0\x13\xc0\x14\x00\x9c\x00\x9d\x00\x2f\x00\x35\x01\x00" +
|
||||
"\x01\x93")
|
||||
G(2)
|
||||
S("\x00\x00\x00\x00")
|
||||
Open()
|
||||
Open()
|
||||
S("\x00")
|
||||
Open()
|
||||
D()
|
||||
Close()
|
||||
Close()
|
||||
Close()
|
||||
S("\x00\x17\x00\x00\xff\x01\x00\x01\x00\x00\x0a\x00\x0a\x00\x08")
|
||||
G(4)
|
||||
S("\x00\x1d\x00\x17\x00\x18\x00\x0b\x00\x02\x01\x00\x00\x23\x00\x00" +
|
||||
"\x00\x10\x00\x0e\x00\x0c\x02\x68\x32\x08\x68\x74\x74\x70\x2f\x31" +
|
||||
"\x2e\x31\x00\x05\x00\x05\x01\x00\x00\x00\x00\x00\x0d\x00\x12\x00" +
|
||||
"\x10\x04\x03\x08\x04\x04\x01\x05\x03\x08\x05\x05\x01\x08\x06\x06" +
|
||||
"\x01\x00\x12\x00\x00\x00\x33\x00\x2b\x00\x29")
|
||||
G(4)
|
||||
S("\x00\x01\x00\x00\x1d\x00\x20")
|
||||
K()
|
||||
S("\x00\x2d\x00\x02\x01\x01\x00\x2b\x00\x0b\x0a")
|
||||
G(6)
|
||||
S("\x03\x04\x03\x03\x03\x02\x03\x01\x00\x1b\x00\x03\x02\x00\x02")
|
||||
G(3)
|
||||
S("\x00\x01\x00\x00\x15")
|
||||
|
||||
if pad := clientHelloLength - b.Len(); pad > 0 {
|
||||
b.Expand(pad)
|
||||
}
|
||||
return randomOffset
|
||||
}
|
||||
|
||||
// writeClientHello writes faketls ClientHello.
|
||||
//
|
||||
// See https://tools.ietf.org/html/rfc5246#section-7.4.1.1.
|
||||
func writeClientHello(
|
||||
w io.Writer,
|
||||
now clock.Clock,
|
||||
sessionID [32]byte,
|
||||
domain string,
|
||||
secret []byte,
|
||||
) (r [32]byte, err error) {
|
||||
b := &bin.Buffer{
|
||||
Buf: make([]byte, 0, 576),
|
||||
}
|
||||
randomOffset := createClientHello(b, sessionID, domain, [32]byte{})
|
||||
|
||||
// https://github.com/tdlib/td/blob/27d3fdd09d90f6b77ecbcce50b1e86dc4b3dd366/td/mtproto/TlsInit.cpp#L380-L384
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
if _, err := mac.Write(b.Buf); err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "hmac write")
|
||||
}
|
||||
|
||||
s := mac.Sum(nil)
|
||||
copy(b.Buf[randomOffset:randomOffset+32], s)
|
||||
// Overwrite last 4 bytes using final := original ^ timestamp.
|
||||
old := binary.LittleEndian.Uint32(b.Buf[randomOffset+28 : randomOffset+32])
|
||||
old ^= uint32(now.Now().Unix())
|
||||
binary.LittleEndian.PutUint32(b.Buf[randomOffset+28:randomOffset+32], old)
|
||||
|
||||
// Copy ClientRandom for later use.
|
||||
copy(r[:], b.Buf[randomOffset:randomOffset+32])
|
||||
_, err = w.Write(b.Buf)
|
||||
return r, err
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package faketls contains faketls implementation.
|
||||
package faketls
|
||||
@@ -0,0 +1,112 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/clock"
|
||||
"go.mau.fi/mautrix-telegram/pkg/gotd/mtproxy"
|
||||
)
|
||||
|
||||
// FakeTLS implements FakeTLS obfuscation protocol.
|
||||
type FakeTLS struct {
|
||||
rand io.Reader
|
||||
clock clock.Clock
|
||||
conn io.ReadWriter
|
||||
|
||||
version [2]byte
|
||||
firstPacket bool
|
||||
|
||||
readBuf bytes.Buffer
|
||||
readBufMux sync.Mutex
|
||||
}
|
||||
|
||||
// NewFakeTLS creates new FakeTLS.
|
||||
func NewFakeTLS(r io.Reader, conn io.ReadWriter) *FakeTLS {
|
||||
return &FakeTLS{
|
||||
rand: r,
|
||||
clock: clock.System,
|
||||
conn: conn,
|
||||
version: Version12Bytes,
|
||||
readBuf: bytes.Buffer{},
|
||||
}
|
||||
}
|
||||
|
||||
// Handshake performs FakeTLS handshake.
|
||||
func (o *FakeTLS) Handshake(protocol [4]byte, dc int, s mtproxy.Secret) error {
|
||||
o.readBufMux.Lock()
|
||||
o.readBuf.Reset()
|
||||
o.readBufMux.Unlock()
|
||||
|
||||
var sessionID [32]byte
|
||||
if _, err := o.rand.Read(sessionID[:]); err != nil {
|
||||
return errors.Wrap(err, "generate sessionID")
|
||||
}
|
||||
|
||||
clientDigest, err := writeClientHello(o.conn, o.clock, sessionID, s.CloakHost, s.Secret)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "send ClientHello")
|
||||
}
|
||||
|
||||
if err := readServerHello(o.conn, clientDigest, s.Secret); err != nil {
|
||||
return errors.Wrap(err, "receive ServerHello")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements io.Writer.
|
||||
func (o *FakeTLS) Write(b []byte) (n int, err error) {
|
||||
// Some proxies require sending first packet with RecordTypeChangeCipherSpec.
|
||||
//
|
||||
// See https://github.com/tdlib/td/blob/master/td/mtproto/TcpTransport.cpp#L266.
|
||||
if !o.firstPacket {
|
||||
_, err = writeRecord(o.conn, record{
|
||||
Type: RecordTypeChangeCipherSpec,
|
||||
Version: o.version,
|
||||
Data: []byte("\x01"),
|
||||
})
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "write first TLS packet")
|
||||
}
|
||||
o.firstPacket = true
|
||||
}
|
||||
n, err = writeRecord(o.conn, record{
|
||||
Type: RecordTypeApplication,
|
||||
Version: o.version,
|
||||
Data: b,
|
||||
})
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "write TLS record")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Read implements io.Reader.
|
||||
func (o *FakeTLS) Read(b []byte) (n int, err error) {
|
||||
o.readBufMux.Lock()
|
||||
defer o.readBufMux.Unlock()
|
||||
|
||||
if o.readBuf.Len() > 0 {
|
||||
return o.readBuf.Read(b)
|
||||
}
|
||||
|
||||
rec, err := readRecord(o.conn)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "read TLS record")
|
||||
}
|
||||
|
||||
switch rec.Type {
|
||||
case RecordTypeChangeCipherSpec:
|
||||
case RecordTypeApplication:
|
||||
case RecordTypeHandshake:
|
||||
return 0, errors.New("unexpected record type handshake")
|
||||
default:
|
||||
return 0, errors.Errorf("unsupported record type %v", rec.Type)
|
||||
}
|
||||
o.readBuf.Write(rec.Data)
|
||||
|
||||
return o.readBuf.Read(b)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/gotd/neo"
|
||||
)
|
||||
|
||||
func TestTLS(t *testing.T) {
|
||||
a := require.New(t)
|
||||
secret := [32]byte{}
|
||||
sessionID := [32]byte{}
|
||||
c := neo.NewTime(time.Date(2010, 10, 10, 1, 1, 1, 0, time.UTC))
|
||||
|
||||
b := bytes.NewBuffer(nil)
|
||||
_, err := writeClientHello(b, c, sessionID, "google.com", secret[:])
|
||||
a.NoError(err)
|
||||
|
||||
testVector := []byte{
|
||||
0x16, 0x03, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0xfc, 0x03, 0x03, 0xf9, 0x75, 0x5f, 0xdd, 0xb9,
|
||||
0xe3, 0x46, 0x57, 0x5a, 0x26, 0x71, 0xfa, 0x29, 0x7f, 0xab, 0xf0, 0xa1, 0xf3, 0x69, 0x4f, 0x72,
|
||||
0xe0, 0xc3, 0x8f, 0x62, 0x77, 0x5c, 0x8f, 0x5a, 0xf8, 0xa2, 0xa9, 0x20, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x13, 0x01,
|
||||
0x13, 0x02, 0x13, 0x03, 0xc0, 0x2b, 0xc0, 0x2f, 0xc0, 0x2c, 0xc0, 0x30, 0xcc, 0xa9, 0xcc, 0xa8,
|
||||
0xc0, 0x13, 0xc0, 0x14, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f, 0x00, 0x35, 0x01, 0x00, 0x01, 0x93,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0x00, 0x0a, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
||||
0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x00, 0x17, 0x00, 0x00, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0a,
|
||||
0x00, 0x0a, 0x00, 0x08, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00,
|
||||
0x00, 0x23, 0x00, 0x00, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x02, 0x68, 0x32, 0x08, 0x68, 0x74,
|
||||
0x74, 0x70, 0x2f, 0x31, 0x2e, 0x31, 0x00, 0x05, 0x00, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x0d, 0x00, 0x12, 0x00, 0x10, 0x04, 0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05,
|
||||
0x01, 0x08, 0x06, 0x06, 0x01, 0x00, 0x12, 0x00, 0x00, 0x00, 0x33, 0x00, 0x2b, 0x00, 0x29, 0x00,
|
||||
0x01, 0x00, 0x00, 0x1d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x02, 0x01, 0x01, 0x00, 0x2b, 0x00, 0x0b,
|
||||
0x0a, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x03, 0x01, 0x00, 0x1b, 0x00, 0x03, 0x02, 0x00, 0x02,
|
||||
0x00, 0x01, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
}
|
||||
a.Equal(testVector, b.Bytes())
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
)
|
||||
|
||||
const maxTLSRecordDataLength = 16384 + 24
|
||||
|
||||
type record struct {
|
||||
Type RecordType
|
||||
Version [2]byte
|
||||
Data []byte
|
||||
}
|
||||
|
||||
func readRecord(r io.Reader) (record, error) {
|
||||
rec := record{}
|
||||
|
||||
buf := make([]byte, 5)
|
||||
if _, err := io.ReadFull(r, buf); err != nil {
|
||||
return record{}, err
|
||||
}
|
||||
|
||||
rec.Type = RecordType(buf[0])
|
||||
versionRaw := buf[1:3]
|
||||
switch {
|
||||
case bytes.Equal(versionRaw, Version13Bytes[:]):
|
||||
rec.Version = Version13Bytes
|
||||
case bytes.Equal(versionRaw, Version12Bytes[:]):
|
||||
rec.Version = Version12Bytes
|
||||
case bytes.Equal(versionRaw, Version11Bytes[:]):
|
||||
rec.Version = Version11Bytes
|
||||
case bytes.Equal(versionRaw, Version10Bytes[:]):
|
||||
rec.Version = Version10Bytes
|
||||
default:
|
||||
return record{}, errors.Errorf("unknown protocol version %v", versionRaw)
|
||||
}
|
||||
|
||||
length := binary.BigEndian.Uint16(buf[3:])
|
||||
if length > maxTLSRecordDataLength {
|
||||
return record{}, errors.New("record length is too big")
|
||||
}
|
||||
|
||||
rec.Data = make([]byte, length)
|
||||
if _, err := io.ReadFull(r, rec.Data); err != nil {
|
||||
return record{}, err
|
||||
}
|
||||
|
||||
return rec, nil
|
||||
}
|
||||
|
||||
func writeRecord(w io.Writer, r record) (int, error) {
|
||||
buf := [...]byte{
|
||||
byte(r.Type),
|
||||
r.Version[0], r.Version[1],
|
||||
}
|
||||
|
||||
if _, err := w.Write(buf[:]); err != nil {
|
||||
return 0, errors.Wrap(err, "type and version")
|
||||
}
|
||||
|
||||
binary.BigEndian.PutUint16(buf[:2], uint16(len(r.Data)))
|
||||
if _, err := w.Write(buf[:2]); err != nil {
|
||||
return 0, errors.Wrap(err, "data length")
|
||||
}
|
||||
|
||||
n, err := w.Write(r.Data)
|
||||
if err != nil {
|
||||
return 0, errors.Wrap(err, "data")
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRecord(t *testing.T) {
|
||||
a := require.New(t)
|
||||
r := record{
|
||||
Type: RecordTypeApplication,
|
||||
Version: Version10Bytes,
|
||||
Data: []byte(`abcd`),
|
||||
}
|
||||
buf := bytes.NewBuffer(nil)
|
||||
|
||||
_, err := writeRecord(buf, r)
|
||||
a.NoError(err)
|
||||
r2, err := readRecord(buf)
|
||||
a.NoError(err)
|
||||
a.Equal(r, r2)
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
|
||||
"github.com/go-faster/errors"
|
||||
)
|
||||
|
||||
// readServerHello reads faketls ServerHello.
|
||||
func readServerHello(r io.Reader, clientRandom [32]byte, secret []byte) error {
|
||||
packetBuf := bytes.NewBuffer(nil)
|
||||
r = io.TeeReader(r, packetBuf)
|
||||
|
||||
handshake, err := readRecord(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "handshake record")
|
||||
}
|
||||
if handshake.Type != RecordTypeHandshake {
|
||||
return errors.Wrap(err, "unexpected record type")
|
||||
}
|
||||
|
||||
changeCipher, err := readRecord(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "change cipher record")
|
||||
}
|
||||
if changeCipher.Type != RecordTypeChangeCipherSpec {
|
||||
return errors.Wrap(err, "unexpected record type")
|
||||
}
|
||||
|
||||
cert, err := readRecord(r)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cert record")
|
||||
}
|
||||
if cert.Type != RecordTypeApplication {
|
||||
return errors.Wrap(err, "unexpected record type")
|
||||
}
|
||||
|
||||
// `$record_header = type 1 byte + version 2 bytes + payload_length 2 bytes = 5 bytes`
|
||||
// `$server_hello_header = type 1 bytes + version 2 bytes + length 3 bytes = 6 bytes`
|
||||
// `$offset = $record_header + $server_hello_header = 11 bytes`
|
||||
const serverRandomOffset = 11
|
||||
packet := packetBuf.Bytes()
|
||||
// Copy original digest.
|
||||
var originalDigest [32]byte
|
||||
copy(originalDigest[:], packet[serverRandomOffset:serverRandomOffset+32])
|
||||
// Fill original digest by zeros.
|
||||
var zeros [32]byte
|
||||
copy(packet[serverRandomOffset:serverRandomOffset+32], zeros[:])
|
||||
|
||||
mac := hmac.New(sha256.New, secret)
|
||||
if _, err := mac.Write(clientRandom[:]); err != nil {
|
||||
return errors.Wrap(err, "hmac write")
|
||||
}
|
||||
if _, err := mac.Write(packet); err != nil {
|
||||
return errors.Wrap(err, "hmac write")
|
||||
}
|
||||
if !bytes.Equal(mac.Sum(nil), originalDigest[:]) {
|
||||
return errors.New("hmac digest mismatch")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package faketls
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_readServerHello(t *testing.T) {
|
||||
p := filepath.Join("testdata", "server_hello")
|
||||
entries, err := os.ReadDir(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
clientRandom := map[string][32]uint8{
|
||||
"alexbers.hex": {
|
||||
0xa1, 0x32, 0xe3, 0x91, 0x60, 0x83, 0xb3, 0x14, 0xc1, 0xb9, 0x74, 0xd0, 0x57, 0x85, 0xe8, 0xee,
|
||||
0x70, 0x45, 0x6e, 0x5f, 0x86, 0x6d, 0x96, 0x57, 0xd5, 0x0a, 0x5c, 0x08, 0xea, 0x38, 0x31, 0x8e,
|
||||
},
|
||||
"mtgv2.hex": {
|
||||
0xca, 0x36, 0xbb, 0xa8, 0x33, 0x80, 0x9a, 0x33, 0xaa, 0x62, 0x7e, 0xbb, 0x5a, 0x32, 0xa1, 0x01,
|
||||
0x02, 0xd1, 0xa6, 0x1e, 0x1e, 0x6c, 0x58, 0xa4, 0x61, 0xd9, 0x34, 0x57, 0x4d, 0x2e, 0x2e, 0xa3,
|
||||
},
|
||||
}
|
||||
secret := []uint8{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
t.Error("Unexpected directory in testdata")
|
||||
continue
|
||||
}
|
||||
fileName := entry.Name()
|
||||
|
||||
t.Run(fileName, func(t *testing.T) {
|
||||
a := require.New(t)
|
||||
|
||||
data, err := os.ReadFile(filepath.Join(p, fileName))
|
||||
a.NoError(err)
|
||||
|
||||
decode, err := hex.DecodeString(strings.TrimSpace(string(data)))
|
||||
a.NoError(err)
|
||||
|
||||
r := bytes.NewReader(decode)
|
||||
a.NoError(readServerHello(r, clientRandom[entry.Name()], secret))
|
||||
|
||||
a.Zero(r.Len(), "should read all data")
|
||||
})
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
160303007a02000076030304794e0ec450abbe0de461b3088d0c487114bdf377733be767eb99cf92ad7eac200de22030bd1329ebfffc70476cf3075efbb95aea776bfa96ab6788c4bff59b2f130100002e002b0002030400330024001d0020df3a68806eecc284a06d8cd934d2a6f1486ab47759457cd0a7a75883fd7e725614030300010117030305c096a8cd3e601b32e3703565d402547894916120178d2330163d3b13e0d7bca02b49fadd55111c2a69fcc75b8e56bdf567eaab01337b19714345e4222c06067cec94dfcdfefc82d2294893ed16d5953fbfc3f7fece2e690dedf46d41b698438237bdee2cb87af0b082e7036d8d42cf9f994407af21b888583f70f5b6a6182881bce5e802b2afd6f5aa45ba043388457010fd649e2c4b98efe11eae85743cbc37b256b06d08b36110ff923febac033487ff8a7fc422b6cd95c2056fa6b15585b34dc21cf588bc2ce0b84d230ff4b97c5e15ffe8a0cc0cc29768d2a17d590e7d5cc082afac040b4e6159a67405d6164f8870704cff8d492afb79b7d93953271f7e7fbd89c8489c99d92e4f3747213deeb5db0feabad6fc1217308bb68c84282ac2cc3d2e1b7e76f86b35d06137fc90fc228995a25f87dfa369dc97b027a76d2ad14f7f1cd60d2ee634c4f3fec49ea5d1d9582b124a4dd7ad082fd2dae39cb59612d67c9eb320bf85f1d8caa72910cda30f57ca888cba453ee3604dcad3ba0768429b4c51855499aba65070c3e2fcbe020c60376e9823c43da8dc098d22eec9c05514d8dc94bc5b8e34812356d44be5d02755643a297e84d126d0cbb628da90cf88d3a0e2c2ad03d34ca3c4d0d1cd35d7f5db041ea2e1a2cb27413c6d8dbbbe3914bfd651ebcc2cadc66083143147f5b8b2534b2d87dc708a9e1fc13ae1fe7055ad3e8b267a63088b2c5e119e2a2540924e7c76e4b0740bf99c0a95be7cc110b6c2432afa1de48b33ddd8a6429dfcfa87c140c435f3c7277cac129697ac8667a952f97688cfe570af4a9ee8dee285c94b459f7836a57c58d02c16e78a900de75728e30b22d37845db718e1fcd03bf85839bbfe16bfd3c8c10e301f247e177a00eb07e439ac5be339e63f057a58ea1ad54ba311866fb977788da894c4c097f78727c72531895cdc98d1976883238c8af3f1f753f1eda49396c36093b2170fc7b577bf82b282be6843b03d74c9a6b82d9f3c6791e42e8e90612ed926b7f26d89d09c62461f9faa4c647a0218f62aa272882777624da48f66daa9d998cf4ccf80b7248f0adbfd329ffa047b514ce8d9c64a55f303438f385726946be120ad2c52c3a3d0f26f4c196994fcef3da70703e06280283a864d612c40054186b767e7fc7df68d272ff7f2f80d4cdb1ae53df04c90f944e3b00316007d69e67531e45b6a3f99cdc60a6f43c77552a1d41f341448148f30063457060a824508704ec807bb41d6706f975ba7a5d56b350e06b01600eb3c627d512a437b2033a82f92bba0fbb07ae01ca2b3a6b2a72f3a935f52feea83751fbaddf81c8bcfe38c810ca376bb1c731e57d66e3e023f975421abc5dfcf8e176bc1ae5ac8849cffe3754ea2950afc4db6baa9fbd2c7d14bbc8c1042d017d2ae766d40729f08c2ff5e32afe96325bae777f3f5e519278fb3c111b2fefc1082309d89aea356542c932c19664f4f02943f83b7e1f0db48a2e4e3ec3d7eea5718e5a9d7bf9294ca7bbf8baa8857dc6a6b04a46fb8654091a7e599f5aa5fd2084091b3024b101be86baed574a587b5b945b16af190d6e759353be612b280cac604960b690a7c831353a767cb20551b397e7ae6a3293b7db12ca996fb823716e004b3399a2b7f37520844f7fe377a345dc2a0c80b64bffdef417faa610ac0ada3bd6fbff61f8e08fbdf66a48e3434c9f46c9dcb73c48526a2caff41029406950c768dc6a215d520f1901b12024315ed5fd8de0700b55b07e545f5ffd6037e2b23433e186951320104ab534d2fcfd9d37b93172933a9f7ecc3f007b01ffab8c902287b1d70c214e4c5b54f3d3e91e740e14cac69525504fdc35ed0322561e83d5d7fa90859140342429761cc18e1ff1f133e3535368235bb1a77a6373008cbd45d4495ae858d601c31532b8f9e8e5ebbebaf73fd9d0cbddaa866b8017c415fbc37df38c34f6b2bc99354b4d52066f8a89beafe8da91275abee0531ea6a28c50a43117fa774855e9106d7177a5408f64aa2e7a58bdc89873d506ff2bf26e21a232362d76c15686dd8b19c13fdafaae357c5229e1f4
|
||||
@@ -0,0 +1,35 @@
|
||||
package faketls
|
||||
|
||||
// RecordType represents TLS record type byte.
|
||||
type RecordType uint8
|
||||
|
||||
const (
|
||||
// RecordTypeChangeCipherSpec is ChangeCipherSpec record type byte.
|
||||
RecordTypeChangeCipherSpec RecordType = 0x14
|
||||
// RecordTypeAlert is Alert record type byte.
|
||||
RecordTypeAlert RecordType = 0x15
|
||||
// RecordTypeHandshake is Handshake record type byte.
|
||||
RecordTypeHandshake RecordType = 0x16
|
||||
// RecordTypeApplication is Application record type byte.
|
||||
RecordTypeApplication RecordType = 0x17
|
||||
// RecordTypeHeartbeat is Heartbeat record type byte.
|
||||
RecordTypeHeartbeat RecordType = 0x18
|
||||
)
|
||||
|
||||
// HandshakeType represents TLS handshake record type byte.
|
||||
type HandshakeType uint8
|
||||
|
||||
const (
|
||||
// HandshakeTypeClient is client handshake message type.
|
||||
HandshakeTypeClient HandshakeType = 0x01
|
||||
// HandshakeTypeServer is server handshake message type.
|
||||
HandshakeTypeServer HandshakeType = 0x02
|
||||
)
|
||||
|
||||
// Possible versions.
|
||||
var (
|
||||
Version10Bytes = [2]byte{0x03, 0x01}
|
||||
Version11Bytes = [2]byte{0x03, 0x02}
|
||||
Version12Bytes = [2]byte{0x03, 0x03}
|
||||
Version13Bytes = [2]byte{0x03, 0x04}
|
||||
)
|
||||
Reference in New Issue
Block a user