Make key lengths explicit

pull/110/head
Andy Wang 4 years ago
parent 443aeecf5f
commit c1f3408c2c

@ -71,8 +71,8 @@ func dispatchConnection(conn net.Conn, sta *server.State) {
return
}
sessionKey := make([]byte, 32)
util.CryptoRandRead(sessionKey)
var sessionKey [32]byte
util.CryptoRandRead(sessionKey[:])
obfuscator, err := mux.GenerateObfs(ci.EncryptionMethod, sessionKey, ci.Transport.HasRecordLayer())
if err != nil {
log.Error(err)

@ -65,7 +65,7 @@ func (DirectTLS) UnitReadFunc() func(net.Conn, []byte) (int, error) { return uti
// PrepareConnection handles the TLS handshake for a given conn and returns the sessionKey
// if the server proceed with Cloak authentication
func (tls DirectTLS) PrepareConnection(authInfo *authInfo, conn net.Conn) (preparedConn net.Conn, sessionKey []byte, err error) {
func (tls DirectTLS) PrepareConnection(authInfo *authInfo, conn net.Conn) (preparedConn net.Conn, sessionKey [32]byte, err error) {
preparedConn = conn
payload, sharedSecret := makeAuthenticationPayload(authInfo, rand.Reader, time.Now())
chOnly := tls.browser.composeClientHello(genStegClientHello(payload, authInfo.MockDomain))
@ -86,10 +86,11 @@ func (tls DirectTLS) PrepareConnection(authInfo *authInfo, conn net.Conn) (prepa
encrypted := append(buf[11:43], buf[89:121]...)
nonce := encrypted[0:12]
ciphertextWithTag := encrypted[12:60]
sessionKey, err = util.AESGCMDecrypt(nonce, sharedSecret, ciphertextWithTag)
sessionKeySlice, err := util.AESGCMDecrypt(nonce, sharedSecret[:], ciphertextWithTag)
if err != nil {
return
}
copy(sessionKey[:], sessionKeySlice)
for i := 0; i < 2; i++ {
// ChangeCipherSpec and EncryptedCert (in the format of application data)

@ -30,7 +30,7 @@ type authInfo struct {
// makeAuthenticationPayload generates the ephemeral key pair, calculates the shared secret, and then compose and
// encrypt the authenticationPayload
func makeAuthenticationPayload(authInfo *authInfo, randReader io.Reader, time time.Time) (ret authenticationPayload, sharedSecret []byte) {
func makeAuthenticationPayload(authInfo *authInfo, randReader io.Reader, time time.Time) (ret authenticationPayload, sharedSecret [32]byte) {
/*
Authentication data:
+----------+----------------+---------------------+-------------+--------------+--------+------------+
@ -53,8 +53,8 @@ func makeAuthenticationPayload(authInfo *authInfo, randReader io.Reader, time ti
plaintext[41] |= UNORDERED_FLAG
}
sharedSecret = ecdh.GenerateSharedSecret(ephPv, authInfo.ServerPubKey)
ciphertextWithTag, _ := util.AESGCMEncrypt(ret.randPubKey[:12], sharedSecret, plaintext)
copy(sharedSecret[:], ecdh.GenerateSharedSecret(ephPv, authInfo.ServerPubKey))
ciphertextWithTag, _ := util.AESGCMEncrypt(ret.randPubKey[:12], sharedSecret[:], plaintext)
copy(ret.ciphertextWithTag[:], ciphertextWithTag[:])
return
}

@ -48,7 +48,7 @@ func MakeSession(connConfig *remoteConnConfig, authInfo *authInfo, isAdmin bool)
time.Sleep(time.Second * 3)
goto makeconn
}
var sk []byte
var sk [32]byte
remoteConn, sk, err = connConfig.Transport.PrepareConnection(authInfo, remoteConn)
if err != nil {
remoteConn.Close()
@ -64,7 +64,7 @@ func MakeSession(connConfig *remoteConnConfig, authInfo *authInfo, isAdmin bool)
wg.Wait()
log.Debug("All underlying connections established")
sessionKey := _sessionKey.Load().([]byte)
sessionKey := _sessionKey.Load().([32]byte)
obfuscator, err := mux.GenerateObfs(authInfo.EncryptionMethod, sessionKey, connConfig.Transport.HasRecordLayer())
if err != nil {
log.Fatal(err)

@ -3,7 +3,7 @@ package client
import "net"
type Transport interface {
PrepareConnection(*authInfo, net.Conn) (net.Conn, []byte, error)
PrepareConnection(*authInfo, net.Conn) (net.Conn, [32]byte, error)
HasRecordLayer() bool
UnitReadFunc() func(net.Conn, []byte) (int, error)
}

@ -22,7 +22,7 @@ type WSOverTLS struct {
func (WSOverTLS) HasRecordLayer() bool { return false }
func (WSOverTLS) UnitReadFunc() func(net.Conn, []byte) (int, error) { return util.ReadWebSocket }
func (ws WSOverTLS) PrepareConnection(authInfo *authInfo, cdnConn net.Conn) (preparedConn net.Conn, sessionKey []byte, err error) {
func (ws WSOverTLS) PrepareConnection(authInfo *authInfo, cdnConn net.Conn) (preparedConn net.Conn, sessionKey [32]byte, err error) {
utlsConfig := &utls.Config{
ServerName: authInfo.MockDomain,
InsecureSkipVerify: true,
@ -36,7 +36,7 @@ func (ws WSOverTLS) PrepareConnection(authInfo *authInfo, cdnConn net.Conn) (pre
u, err := url.Parse("ws://" + ws.cdnDomainPort)
if err != nil {
return preparedConn, nil, fmt.Errorf("failed to parse ws url: %v", err)
return preparedConn, sessionKey, fmt.Errorf("failed to parse ws url: %v", err)
}
payload, sharedSecret := makeAuthenticationPayload(authInfo, rand.Reader, time.Now())
@ -44,7 +44,7 @@ func (ws WSOverTLS) PrepareConnection(authInfo *authInfo, cdnConn net.Conn) (pre
header.Add("hidden", base64.StdEncoding.EncodeToString(append(payload.randPubKey[:], payload.ciphertextWithTag[:]...)))
c, _, err := websocket.NewClient(preparedConn, u, header, 16480, 16480)
if err != nil {
return preparedConn, nil, fmt.Errorf("failed to handshake: %v", err)
return preparedConn, sessionKey, fmt.Errorf("failed to handshake: %v", err)
}
preparedConn = &util.WebSocketConn{Conn: c}
@ -52,15 +52,19 @@ func (ws WSOverTLS) PrepareConnection(authInfo *authInfo, cdnConn net.Conn) (pre
buf := make([]byte, 128)
n, err := preparedConn.Read(buf)
if err != nil {
return preparedConn, nil, fmt.Errorf("failed to read reply: %v", err)
return preparedConn, sessionKey, fmt.Errorf("failed to read reply: %v", err)
}
if n != 60 {
return preparedConn, nil, errors.New("reply must be 60 bytes")
return preparedConn, sessionKey, errors.New("reply must be 60 bytes")
}
reply := buf[:60]
sessionKey, err = util.AESGCMDecrypt(reply[:12], sharedSecret, reply[12:])
sessionKeySlice, err := util.AESGCMDecrypt(reply[:12], sharedSecret[:], reply[12:])
if err != nil {
return
}
copy(sessionKey[:], sessionKeySlice)
return
}

@ -144,21 +144,14 @@ func MakeDeobfs(salsaKey [32]byte, payloadCipher cipher.AEAD, hasRecordLayer boo
return deobfs
}
func GenerateObfs(encryptionMethod byte, sessionKey []byte, hasRecordLayer bool) (obfuscator *Obfuscator, err error) {
if len(sessionKey) != 32 {
err = errors.New("sessionKey size must be 32 bytes")
}
var salsaKey [32]byte
copy(salsaKey[:], sessionKey)
func GenerateObfs(encryptionMethod byte, sessionKey [32]byte, hasRecordLayer bool) (obfuscator *Obfuscator, err error) {
var payloadCipher cipher.AEAD
switch encryptionMethod {
case E_METHOD_PLAIN:
payloadCipher = nil
case E_METHOD_AES_GCM:
var c cipher.Block
c, err = aes.NewCipher(sessionKey)
c, err = aes.NewCipher(sessionKey[:])
if err != nil {
return
}
@ -167,7 +160,7 @@ func GenerateObfs(encryptionMethod byte, sessionKey []byte, hasRecordLayer bool)
return
}
case E_METHOD_CHACHA20_POLY1305:
payloadCipher, err = chacha20poly1305.New(sessionKey)
payloadCipher, err = chacha20poly1305.New(sessionKey[:])
if err != nil {
return
}
@ -176,8 +169,8 @@ func GenerateObfs(encryptionMethod byte, sessionKey []byte, hasRecordLayer bool)
}
obfuscator = &Obfuscator{
MakeObfs(salsaKey, payloadCipher, hasRecordLayer),
MakeDeobfs(salsaKey, payloadCipher, hasRecordLayer),
MakeObfs(sessionKey, payloadCipher, hasRecordLayer),
MakeDeobfs(sessionKey, payloadCipher, hasRecordLayer),
sessionKey,
}
return

@ -25,7 +25,7 @@ type Obfuscator struct {
Obfs Obfser
// Remove TLS header, decrypt and unmarshall frames
Deobfs Deobfser
SessionKey []byte
SessionKey [32]byte
}
type switchboardStrategy int

@ -33,13 +33,13 @@ func (TLS) processFirstPacket(clientHello []byte, privateKey crypto.PrivateKey)
return
}
respond = TLS{}.makeResponder(ch.sessionId, fragments.sharedSecret[:])
respond = TLS{}.makeResponder(ch.sessionId, fragments.sharedSecret)
return
}
func (TLS) makeResponder(clientHelloSessionId []byte, sharedSecret []byte) Responder {
respond := func(originalConn net.Conn, sessionKey []byte) (preparedConn net.Conn, err error) {
func (TLS) makeResponder(clientHelloSessionId []byte, sharedSecret [32]byte) Responder {
respond := func(originalConn net.Conn, sessionKey [32]byte) (preparedConn net.Conn, err error) {
preparedConn = originalConn
reply, err := composeReply(clientHelloSessionId, sharedSecret, sessionKey)
if err != nil {

@ -162,11 +162,11 @@ func parseClientHello(data []byte) (ret *ClientHello, err error) {
return
}
func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte) ([]byte, error) {
func composeServerHello(sessionId []byte, sharedSecret [32]byte, sessionKey [32]byte) ([]byte, error) {
nonce := make([]byte, 12)
util.CryptoRandRead(nonce)
encryptedKey, err := util.AESGCMEncrypt(nonce, sharedSecret, sessionKey) // 32 + 16 = 48 bytes
encryptedKey, err := util.AESGCMEncrypt(nonce, sharedSecret[:], sessionKey[:]) // 32 + 16 = 48 bytes
if err != nil {
return nil, err
}
@ -198,7 +198,7 @@ func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte
// composeReply composes the ServerHello, ChangeCipherSpec and an ApplicationData messages
// together with their respective record layers into one byte slice.
func composeReply(clientHelloSessionId []byte, sharedSecret []byte, sessionKey []byte) ([]byte, error) {
func composeReply(clientHelloSessionId []byte, sharedSecret [32]byte, sessionKey [32]byte) ([]byte, error) {
TLS12 := []byte{0x03, 0x03}
sh, err := composeServerHello(clientHelloSessionId, sharedSecret, sessionKey)
if err != nil {

@ -6,7 +6,7 @@ import (
"net"
)
type Responder = func(originalConn net.Conn, sessionKey []byte) (preparedConn net.Conn, err error)
type Responder = func(originalConn net.Conn, sessionKey [32]byte) (preparedConn net.Conn, err error)
type Transport interface {
HasRecordLayer() bool
UnitReadFunc() func(net.Conn, []byte) (int, error)

@ -35,13 +35,13 @@ func (WebSocket) processFirstPacket(reqPacket []byte, privateKey crypto.PrivateK
return
}
respond = WebSocket{}.makeResponder(reqPacket, fragments.sharedSecret[:])
respond = WebSocket{}.makeResponder(reqPacket, fragments.sharedSecret)
return
}
func (WebSocket) makeResponder(reqPacket []byte, sharedSecret []byte) Responder {
respond := func(originalConn net.Conn, sessionKey []byte) (preparedConn net.Conn, err error) {
func (WebSocket) makeResponder(reqPacket []byte, sharedSecret [32]byte) Responder {
respond := func(originalConn net.Conn, sessionKey [32]byte) (preparedConn net.Conn, err error) {
handler := newWsHandshakeHandler()
// For an explanation of the following 3 lines, see the comments in websocketAux.go
@ -53,7 +53,7 @@ func (WebSocket) makeResponder(reqPacket []byte, sharedSecret []byte) Responder
util.CryptoRandRead(nonce)
// reply: [12 bytes nonce][32 bytes encrypted session key][16 bytes authentication tag]
encryptedKey, err := util.AESGCMEncrypt(nonce, sharedSecret, sessionKey) // 32 + 16 = 48 bytes
encryptedKey, err := util.AESGCMEncrypt(nonce, sharedSecret[:], sessionKey[:]) // 32 + 16 = 48 bytes
if err != nil {
err = fmt.Errorf("failed to encrypt reply: %v", err)
return

Loading…
Cancel
Save