Cloak/internal/client/TLS.go

86 lines
2.3 KiB
Go
Raw Normal View History

2019-08-02 15:02:25 +00:00
package client
2018-10-07 17:09:45 +00:00
import (
"encoding/binary"
"github.com/cbeuw/Cloak/internal/util"
2019-08-06 14:50:33 +00:00
"net"
log "github.com/sirupsen/logrus"
2018-10-07 17:09:45 +00:00
)
2019-08-16 23:18:19 +00:00
type browser interface {
composeClientHello(chHiddenData) []byte
2018-10-07 17:09:45 +00:00
}
2019-08-02 00:01:19 +00:00
func makeServerName(serverName string) []byte {
2018-10-07 17:09:45 +00:00
serverNameListLength := make([]byte, 2)
binary.BigEndian.PutUint16(serverNameListLength, uint16(len(serverName)+3))
serverNameType := []byte{0x00} // host_name
serverNameLength := make([]byte, 2)
binary.BigEndian.PutUint16(serverNameLength, uint16(len(serverName)))
ret := make([]byte, 2+1+2+len(serverName))
copy(ret[0:2], serverNameListLength)
copy(ret[2:3], serverNameType)
copy(ret[3:5], serverNameLength)
copy(ret[5:], serverName)
return ret
}
// addExtensionRecord, add type, length to extension data
func addExtRec(typ []byte, data []byte) []byte {
length := make([]byte, 2)
binary.BigEndian.PutUint16(length, uint16(len(data)))
ret := make([]byte, 2+2+len(data))
copy(ret[0:2], typ)
copy(ret[2:4], length)
copy(ret[4:], data)
return ret
}
2019-09-02 13:03:10 +00:00
type DirectTLS struct {
2019-08-31 17:01:39 +00:00
Transport
}
2019-09-02 13:03:10 +00:00
func (DirectTLS) HasRecordLayer() bool { return true }
func (DirectTLS) UnitReadFunc() func(net.Conn, []byte) (int, error) { return util.ReadTLS }
2019-09-01 19:23:45 +00:00
2019-08-20 21:43:04 +00:00
// PrepareConnection handles the TLS handshake for a given conn and returns the sessionKey
// if the server proceed with Cloak authentication
2019-09-02 13:03:10 +00:00
func (DirectTLS) PrepareConnection(sta *State, conn net.Conn) (preparedConn net.Conn, sessionKey []byte, err error) {
2019-09-01 19:23:45 +00:00
preparedConn = conn
hd, sharedSecret := makeHiddenData(sta)
2019-08-16 23:18:19 +00:00
chOnly := sta.browser.composeClientHello(hd)
chWithRecordLayer := util.AddRecordLayer(chOnly, []byte{0x16}, []byte{0x03, 0x01})
2019-09-01 19:23:45 +00:00
_, err = preparedConn.Write(chWithRecordLayer)
2019-08-06 14:50:33 +00:00
if err != nil {
return
}
log.Trace("client hello sent successfully")
buf := make([]byte, 1024)
log.Trace("waiting for ServerHello")
2019-09-01 19:23:45 +00:00
_, err = util.ReadTLS(preparedConn, buf)
2019-08-06 14:50:33 +00:00
if err != nil {
return
}
encrypted := append(buf[11:43], buf[89:121]...)
nonce := encrypted[0:12]
2019-08-20 21:43:04 +00:00
ciphertextWithTag := encrypted[12:60]
sessionKey, err = util.AESGCMDecrypt(nonce, sharedSecret, ciphertextWithTag)
if err != nil {
return
}
for i := 0; i < 2; i++ {
// ChangeCipherSpec and EncryptedCert (in the format of application data)
2019-09-01 19:23:45 +00:00
_, err = util.ReadTLS(preparedConn, buf)
if err != nil {
return
}
2019-08-06 14:50:33 +00:00
}
2019-09-01 19:23:45 +00:00
return preparedConn, sessionKey, nil
2019-08-06 14:50:33 +00:00
}