Cloak/internal/server/auth.go

75 lines
2.0 KiB
Go
Raw Normal View History

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"
"github.com/cbeuw/Cloak/internal/ecdh"
2018-10-14 19:32:54 +00:00
"github.com/cbeuw/Cloak/internal/util"
"log"
2018-10-09 15:07:54 +00:00
)
2019-07-31 22:58:15 +00:00
const SESSION_TICKET_LEN = 192
const PUB_KEY_LEN = 32
const AUTH_TAG_LEN = 16
const USED_STAGNO_LEN = 16 + 16 + 1
func decryptSessionTicket(staticPv crypto.PrivateKey, ticket []byte) (UID []byte, proxyMethod string, encryptionMethod byte, tthKey []byte) {
2019-07-31 22:58:15 +00:00
// sessionTicket: [marshalled ephemeral pub key 32 bytes][encrypted UID 16 bytes, proxy method 16 bytes, encryption method 1 byte][reserved 111 bytes][padding 111 bytes]
ephPub, _ := ecdh.Unmarshal(ticket[0:PUB_KEY_LEN])
tthKey = ecdh.GenerateSharedSecret(staticPv, ephPub)
2019-07-31 22:58:15 +00:00
plain, err := util.AESGCMDecrypt(ticket[0:12], tthKey, ticket[PUB_KEY_LEN:])
2019-06-09 14:03:28 +00:00
if err != nil {
return
2019-06-09 14:03:28 +00:00
}
return plain[0:16], string(bytes.Trim(plain[16:32], "\x00")), plain[32], tthKey
2018-10-09 15:07:54 +00:00
}
func validateRandom(random []byte, UID []byte, time int64) (bool, uint32) {
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)))
front := 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)
copy(preHash[40:56], front)
2018-10-09 15:07:54 +00:00
h := sha256.New()
h.Write(preHash)
sessionID := binary.BigEndian.Uint32(front[0:4])
return bytes.Equal(h.Sum(nil)[0:16], random[16:32]), sessionID
2018-10-09 15:07:54 +00:00
}
func TouchStone(ch *ClientHello, sta *State) (isCK bool, UID []byte, sessionID uint32, proxyMethod string, encryptionMethod byte, tthKey []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-07-31 22:58:15 +00:00
if len(ticket) < PUB_KEY_LEN+USED_STAGNO_LEN+AUTH_TAG_LEN {
2019-06-09 11:05:41 +00:00
return
2018-10-20 20:41:01 +00:00
}
UID, proxyMethod, encryptionMethod, tthKey = decryptSessionTicket(sta.staticPv, ticket)
2019-06-16 01:08:51 +00:00
if len(UID) < 16 {
2019-06-09 14:03:28 +00:00
return
}
isCK, sessionID = 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
}