2018-10-09 15:07:54 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
2018-10-14 19:32:54 +00:00
|
|
|
"crypto"
|
2018-10-09 15:07:54 +00:00
|
|
|
"crypto/sha256"
|
|
|
|
"encoding/binary"
|
|
|
|
"log"
|
2018-10-14 19:32:54 +00:00
|
|
|
|
2019-01-25 00:24:47 +00:00
|
|
|
"github.com/cbeuw/Cloak/internal/ecdh"
|
2018-10-14 19:32:54 +00:00
|
|
|
"github.com/cbeuw/Cloak/internal/util"
|
2018-10-09 15:07:54 +00:00
|
|
|
)
|
|
|
|
|
2018-11-07 21:16:13 +00:00
|
|
|
// input ticket, return UID
|
2019-06-09 11:05:41 +00:00
|
|
|
func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) ([]byte, uint32, string, byte) {
|
2019-01-25 00:24:47 +00:00
|
|
|
ephPub, _ := ecdh.Unmarshal(ticket[0:32])
|
|
|
|
key := ecdh.GenerateSharedSecret(staticPv, ephPub)
|
2019-06-09 14:03:28 +00:00
|
|
|
plain, err := util.AESGCMDecrypt(ticket[0:12], key, ticket[32:101])
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0, "", 0x00
|
|
|
|
}
|
2019-06-09 06:10:22 +00:00
|
|
|
sessionID := binary.BigEndian.Uint32(plain[32:36])
|
2019-06-09 11:05:41 +00:00
|
|
|
return plain[0:32], sessionID, string(bytes.Trim(plain[36:52], "\x00")), plain[52]
|
2018-10-09 15:07:54 +00:00
|
|
|
}
|
|
|
|
|
2018-11-07 21:16:13 +00:00
|
|
|
func validateRandom(random []byte, UID []byte, time int64) bool {
|
2018-10-09 15:07:54 +00:00
|
|
|
t := make([]byte, 8)
|
2018-10-14 19:32:54 +00:00
|
|
|
binary.BigEndian.PutUint64(t, uint64(time/(12*60*60)))
|
|
|
|
rdm := random[0:16]
|
2018-10-09 15:07:54 +00:00
|
|
|
preHash := make([]byte, 56)
|
2018-11-07 21:16:13 +00:00
|
|
|
copy(preHash[0:32], UID)
|
2018-10-09 15:07:54 +00:00
|
|
|
copy(preHash[32:40], t)
|
2018-10-14 19:32:54 +00:00
|
|
|
copy(preHash[40:56], rdm)
|
2018-10-09 15:07:54 +00:00
|
|
|
h := sha256.New()
|
|
|
|
h.Write(preHash)
|
|
|
|
return bytes.Equal(h.Sum(nil)[0:16], random[16:32])
|
|
|
|
}
|
2019-06-09 11:05:41 +00:00
|
|
|
func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte) {
|
2018-10-09 15:07:54 +00:00
|
|
|
var random [32]byte
|
|
|
|
copy(random[:], ch.random)
|
2019-01-19 19:30:32 +00:00
|
|
|
|
|
|
|
sta.usedRandomM.Lock()
|
|
|
|
used := sta.usedRandom[random]
|
|
|
|
sta.usedRandom[random] = int(sta.Now().Unix())
|
|
|
|
sta.usedRandomM.Unlock()
|
|
|
|
|
2018-10-09 15:07:54 +00:00
|
|
|
if used != 0 {
|
|
|
|
log.Println("Replay! Duplicate random")
|
2019-06-09 11:05:41 +00:00
|
|
|
return
|
2018-10-09 15:07:54 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 20:41:01 +00:00
|
|
|
ticket := ch.extensions[[2]byte{0x00, 0x23}]
|
2019-01-19 13:18:13 +00:00
|
|
|
if len(ticket) < 68 {
|
2019-06-09 11:05:41 +00:00
|
|
|
return
|
2018-10-20 20:41:01 +00:00
|
|
|
}
|
2019-06-09 11:05:41 +00:00
|
|
|
UID, sessionID, proxyMethod, encryptionMethod = decryptSessionTicket(sta.staticPv, ticket)
|
2019-06-09 14:03:28 +00:00
|
|
|
if len(UID) < 32 {
|
|
|
|
return
|
|
|
|
}
|
2019-06-09 06:10:22 +00:00
|
|
|
isCK = validateRandom(ch.random, UID, sta.Now().Unix())
|
|
|
|
if !isCK {
|
2019-06-09 11:05:41 +00:00
|
|
|
return
|
2018-10-09 15:07:54 +00:00
|
|
|
}
|
|
|
|
|
2018-11-07 21:16:13 +00:00
|
|
|
return
|
2018-10-09 15:07:54 +00:00
|
|
|
}
|