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) {
|
||||
|
||||
clientHello, sharedSecret := composeClientHello(sta)
|
||||
_, err = conn.Write(clientHello)
|
||||
if err != nil {
|
||||
|
|
@ -58,8 +57,15 @@ func PrepareConnection(sta *State, conn net.Conn) (sessionKey []byte, err error)
|
|||
if err != nil {
|
||||
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)
|
||||
if err != nil {
|
||||
return
|
||||
|
|
|
|||
|
|
@ -28,14 +28,3 @@ func makeHiddenData(sta *State) (random, TLSsessionID, keyShare, sharedSecret []
|
|||
keyShare = ciphertext[32:64]
|
||||
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"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/cbeuw/Cloak/internal/util"
|
||||
"net"
|
||||
|
||||
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
|
||||
serverHello[0] = []byte{0x02} // handshake type
|
||||
serverHello[1] = []byte{0x00, 0x00, 0x76} // length 77
|
||||
serverHello[2] = []byte{0x03, 0x03} // server version
|
||||
xor(sharedSecret, sessionKey)
|
||||
serverHello[3] = sharedSecret // random
|
||||
serverHello[4] = []byte{0x20} // session id length 32
|
||||
serverHello[5] = sessionId // session id
|
||||
serverHello[6] = []byte{0xc0, 0x30} // cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
serverHello[7] = []byte{0x00} // compression method null
|
||||
serverHello[8] = []byte{0x00, 0x2e} // extensions length 46
|
||||
serverHello[0] = []byte{0x02} // handshake type
|
||||
serverHello[1] = []byte{0x00, 0x00, 0x76} // length 77
|
||||
serverHello[2] = []byte{0x03, 0x03} // server version
|
||||
serverHello[3] = append(nonce[0:12], encryptedKey[0:20]...) // random 32 bytes
|
||||
serverHello[4] = []byte{0x20} // session id length 32
|
||||
serverHello[5] = sessionId // session id
|
||||
serverHello[6] = []byte{0xc0, 0x30} // cipher suite TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
|
||||
serverHello[7] = []byte{0x00} // compression method null
|
||||
serverHello[8] = []byte{0x00, 0x2e} // extensions length 46
|
||||
|
||||
keyShare, _ := hex.DecodeString("00330024001d0020")
|
||||
keyExchange := make([]byte, 32)
|
||||
rand.Read(keyExchange)
|
||||
copy(keyExchange, encryptedKey[20:48])
|
||||
rand.Read(keyExchange[28:32])
|
||||
serverHello[9] = append(keyShare, keyExchange...)
|
||||
|
||||
serverHello[10], _ = hex.DecodeString("002b00020304")
|
||||
|
|
@ -189,18 +198,22 @@ func composeServerHello(sessionId []byte, sharedSecret []byte, sessionKey []byte
|
|||
for _, s := range serverHello {
|
||||
ret = append(ret, s...)
|
||||
}
|
||||
return ret
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// composeReply composes the ServerHello, ChangeCipherSpec and Finished messages
|
||||
// together with their respective record layers into one byte slice. The content
|
||||
// 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}
|
||||
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)
|
||||
ret := append(shBytes, ccsBytes...)
|
||||
return ret
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
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 {
|
||||
reply := composeReply(ch, sharedSecret, sessionKey)
|
||||
reply, err := composeReply(ch, sharedSecret, sessionKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = conn.Write(reply)
|
||||
if err != nil {
|
||||
go conn.Close()
|
||||
|
|
|
|||
Loading…
Reference in New Issue