mirror of https://github.com/cbeuw/Cloak
Use AEAD to encrypt session key in ServerHello to provide authentication of the identity of the server
This commit is contained in:
parent
623ca55ab5
commit
1d878b3adb
|
|
@ -44,7 +44,6 @@ func composeClientHello(sta *State) ([]byte, []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func PrepareConnection(sta *State, conn net.Conn) (sessionKey []byte, err error) {
|
func PrepareConnection(sta *State, conn net.Conn) (sessionKey []byte, err error) {
|
||||||
|
|
||||||
clientHello, sharedSecret := composeClientHello(sta)
|
clientHello, sharedSecret := composeClientHello(sta)
|
||||||
_, err = conn.Write(clientHello)
|
_, err = conn.Write(clientHello)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -58,8 +57,15 @@ func PrepareConnection(sta *State, conn net.Conn) (sessionKey []byte, err error)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
serverRandom := buf[11:43]
|
|
||||||
sessionKey = decryptSessionKey(serverRandom, sharedSecret)
|
encrypted := append(buf[11:43], buf[89:121]...)
|
||||||
|
nonce := encrypted[0:12]
|
||||||
|
ciphertext := encrypted[12:60]
|
||||||
|
sessionKey, err = util.AESGCMDecrypt(nonce, sharedSecret, ciphertext)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_, err = util.ReadTLS(conn, buf)
|
_, err = util.ReadTLS(conn, buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,3 @@ func makeHiddenData(sta *State) (random, TLSsessionID, keyShare, sharedSecret []
|
||||||
keyShare = ciphertext[32:64]
|
keyShare = ciphertext[32:64]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func xor(a []byte, b []byte) {
|
|
||||||
for i := range a {
|
|
||||||
a[i] ^= b[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptSessionKey(serverRandom []byte, sharedSecret []byte) []byte {
|
|
||||||
xor(serverRandom, sharedSecret)
|
|
||||||
return serverRandom
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/cbeuw/Cloak/internal/util"
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
@ -166,22 +167,30 @@ func xor(a []byte, b []byte) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte) []byte {
|
func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte) ([]byte, error) {
|
||||||
|
nonce := make([]byte, 12)
|
||||||
|
rand.Read(nonce)
|
||||||
|
|
||||||
|
encryptedKey, err := util.AESGCMEncrypt(nonce, sharedSecret, sessionKey) // 32 + 16 = 48 bytes
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
var serverHello [11][]byte
|
var serverHello [11][]byte
|
||||||
serverHello[0] = []byte{0x02} // handshake type
|
serverHello[0] = []byte{0x02} // handshake type
|
||||||
serverHello[1] = []byte{0x00, 0x00, 0x76} // length 77
|
serverHello[1] = []byte{0x00, 0x00, 0x76} // length 77
|
||||||
serverHello[2] = []byte{0x03, 0x03} // server version
|
serverHello[2] = []byte{0x03, 0x03} // server version
|
||||||
xor(sharedSecret, sessionKey)
|
serverHello[3] = append(nonce[0:12], encryptedKey[0:20]...) // random 32 bytes
|
||||||
serverHello[3] = sharedSecret // random
|
serverHello[4] = []byte{0x20} // session id length 32
|
||||||
serverHello[4] = []byte{0x20} // session id length 32
|
serverHello[5] = sessionId // session id
|
||||||
serverHello[5] = sessionId // session id
|
serverHello[6] = []byte{0xc0, 0x30} // cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||||
serverHello[6] = []byte{0xc0, 0x30} // cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
serverHello[7] = []byte{0x00} // compression method null
|
||||||
serverHello[7] = []byte{0x00} // compression method null
|
serverHello[8] = []byte{0x00, 0x2e} // extensions length 46
|
||||||
serverHello[8] = []byte{0x00, 0x2e} // extensions length 46
|
|
||||||
|
|
||||||
keyShare, _ := hex.DecodeString("00330024001d0020")
|
keyShare, _ := hex.DecodeString("00330024001d0020")
|
||||||
keyExchange := make([]byte, 32)
|
keyExchange := make([]byte, 32)
|
||||||
rand.Read(keyExchange)
|
copy(keyExchange, encryptedKey[20:48])
|
||||||
|
rand.Read(keyExchange[28:32])
|
||||||
serverHello[9] = append(keyShare, keyExchange...)
|
serverHello[9] = append(keyShare, keyExchange...)
|
||||||
|
|
||||||
serverHello[10], _ = hex.DecodeString("002b00020304")
|
serverHello[10], _ = hex.DecodeString("002b00020304")
|
||||||
|
|
@ -189,18 +198,22 @@ func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte
|
||||||
for _, s := range serverHello {
|
for _, s := range serverHello {
|
||||||
ret = append(ret, s...)
|
ret = append(ret, s...)
|
||||||
}
|
}
|
||||||
return ret
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// composeReply composes the ServerHello, ChangeCipherSpec and Finished messages
|
// composeReply composes the ServerHello, ChangeCipherSpec and Finished messages
|
||||||
// together with their respective record layers into one byte slice. The content
|
// together with their respective record layers into one byte slice. The content
|
||||||
// of these messages are random and useless for this plugin
|
// of these messages are random and useless for this plugin
|
||||||
func composeReply(ch *ClientHello, sharedSecret []byte, sessionKey []byte) []byte {
|
func composeReply(ch *ClientHello, sharedSecret []byte, sessionKey []byte) ([]byte, error) {
|
||||||
TLS12 := []byte{0x03, 0x03}
|
TLS12 := []byte{0x03, 0x03}
|
||||||
shBytes := addRecordLayer(composeServerHello(ch.sessionId, sharedSecret, sessionKey), []byte{0x16}, TLS12)
|
sh, err := composeServerHello(ch.sessionId, sharedSecret, sessionKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
shBytes := addRecordLayer(sh, []byte{0x16}, TLS12)
|
||||||
ccsBytes := addRecordLayer([]byte{0x01}, []byte{0x14}, TLS12)
|
ccsBytes := addRecordLayer([]byte{0x01}, []byte{0x14}, TLS12)
|
||||||
ret := append(shBytes, ccsBytes...)
|
ret := append(shBytes, ccsBytes...)
|
||||||
return ret
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrBadClientHello = errors.New("non (or malformed) ClientHello")
|
var ErrBadClientHello = errors.New("non (or malformed) ClientHello")
|
||||||
|
|
@ -228,7 +241,10 @@ func PrepareConnection(firstPacket []byte, sta *State, conn net.Conn) (UID []byt
|
||||||
}
|
}
|
||||||
|
|
||||||
finisher = func(sessionKey []byte) error {
|
finisher = func(sessionKey []byte) error {
|
||||||
reply := composeReply(ch, sharedSecret, sessionKey)
|
reply, err := composeReply(ch, sharedSecret, sessionKey)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
_, err = conn.Write(reply)
|
_, err = conn.Write(reply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
go conn.Close()
|
go conn.Close()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue