actually authenticate messages with challenges and HMACs
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/hpke"
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"log"
|
||||
@@ -26,9 +28,11 @@ var (
|
||||
iface *water.Interface
|
||||
conn *net.UDPConn
|
||||
serverAddr *net.UDPAddr
|
||||
internalIP net.IP = nil
|
||||
internalIP net.IP
|
||||
privKey hpke.PrivateKey
|
||||
multicastKey []byte
|
||||
challengeCh = make(chan []byte, 1)
|
||||
authSecret []byte
|
||||
|
||||
establishMutex sync.Mutex
|
||||
peerPubKeys = shared.NewTMap[string, hpke.PublicKey]()
|
||||
@@ -70,8 +74,23 @@ func register() {
|
||||
}
|
||||
pubKey := privKey.PublicKey()
|
||||
|
||||
// TODO: this probably should be repeated until we get RESP_REGISTER
|
||||
send(shared.BuildPkt(shared.REQ_REGISTER, pubKey.Bytes()))
|
||||
// TODO: all this probably should be retried until we get RESP_REGISTER
|
||||
|
||||
log.Println("requesting register challenge")
|
||||
send(shared.BuildPkt(shared.REQ_GET_CHALLENGE, pubKey.Bytes()))
|
||||
|
||||
challenge := <-challengeCh
|
||||
log.Println("got register challenge")
|
||||
|
||||
authSecret, err = hpke.Open(privKey, hpke.HKDFSHA256(), hpke.ChaCha20Poly1305(), []byte("baalvpn-challenge"), challenge)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
log.Println("registering")
|
||||
mac := hmac.New(sha256.New, authSecret)
|
||||
mac.Write(pubKey.Bytes())
|
||||
send(shared.BuildPkt(shared.REQ_REGISTER, mac.Sum(nil), pubKey.Bytes()))
|
||||
}
|
||||
|
||||
func receivePackets() {
|
||||
@@ -116,11 +135,13 @@ func handleIncomingPkt(pkt []byte) {
|
||||
pktType := binary.LittleEndian.Uint16(pkt[2:])
|
||||
|
||||
switch pktType {
|
||||
case shared.RESP_GET_CHALLENGE:
|
||||
challengeCh <- pkt[4:]
|
||||
case shared.RESP_REGISTER:
|
||||
internalIP = net.IP(pkt[4:20])
|
||||
|
||||
var err error
|
||||
multicastKey, err = hpke.Open(privKey, hpke.HKDFSHA256(), hpke.ChaCha20Poly1305(), []byte("baalvpn"), pkt[20:])
|
||||
multicastKey, err = hpke.Open(privKey, hpke.HKDFSHA256(), hpke.ChaCha20Poly1305(), []byte("baalvpn-register"), pkt[20:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -129,11 +150,11 @@ func handleIncomingPkt(pkt []byte) {
|
||||
setupInterface()
|
||||
go relayPackets()
|
||||
case shared.ENC_PKT:
|
||||
srcIP := net.IP(pkt[20:36]).String()
|
||||
srcIP := net.IP(pkt[52:68]).String()
|
||||
|
||||
sessionKey := getOrEstablishSessionKey(srcIP)
|
||||
|
||||
decryptedPkt, err := DecryptSym(sessionKey, pkt[36:])
|
||||
decryptedPkt, err := DecryptSym(sessionKey, pkt[68:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -143,7 +164,7 @@ func handleIncomingPkt(pkt []byte) {
|
||||
log.Println(err)
|
||||
}
|
||||
case shared.BROADCAST_PKT:
|
||||
decryptedPkt, err := DecryptSym(multicastKey, pkt[4:])
|
||||
decryptedPkt, err := DecryptSym(multicastKey, pkt[36:])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -159,14 +180,14 @@ func handleIncomingPkt(pkt []byte) {
|
||||
}
|
||||
peerPubKeys.Set(respIP, pubKey)
|
||||
case shared.REQ_ESTABLISH:
|
||||
srcIP := net.IP(pkt[20:36]).String()
|
||||
ciphertext := pkt[36:]
|
||||
srcIP := net.IP(pkt[52:68]).String()
|
||||
ciphertext := pkt[68:]
|
||||
|
||||
r, err := hpke.NewRecipient(ciphertext, privKey, hpke.HKDFSHA256(), hpke.ExportOnly(), nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sessionKey, err := r.Export("baalvpn", 32)
|
||||
sessionKey, err := r.Export("baalvpn-establish", 32)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@@ -174,10 +195,9 @@ func handleIncomingPkt(pkt []byte) {
|
||||
log.Println("received session key from", srcIP)
|
||||
peerSessionKeys.Set(srcIP, sessionKey)
|
||||
|
||||
reqData := append(net.ParseIP(srcIP), internalIP...)
|
||||
send(shared.BuildPkt(shared.RESP_ESTABLISH, reqData))
|
||||
send(buildAuthPkt(shared.RESP_ESTABLISH, net.ParseIP(srcIP), internalIP))
|
||||
case shared.RESP_ESTABLISH:
|
||||
srcIP := net.IP(pkt[20:36]).String()
|
||||
srcIP := net.IP(pkt[52:68]).String()
|
||||
log.Println("established session key with", srcIP)
|
||||
peerEstablishAcks.Set(srcIP, true)
|
||||
default:
|
||||
@@ -215,13 +235,12 @@ func getOrEstablishSessionKey(ip string) []byte {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sessionKey, err := sender.Export("baalvpn", 32)
|
||||
sessionKey, err := sender.Export("baalvpn-establish", 32)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reqData := append(net.ParseIP(ip), append(internalIP, ciphertext...)...)
|
||||
send(shared.BuildPkt(shared.REQ_ESTABLISH, reqData))
|
||||
send(buildAuthPkt(shared.REQ_ESTABLISH, net.ParseIP(ip), internalIP, ciphertext))
|
||||
|
||||
for {
|
||||
// TODO: eww
|
||||
@@ -279,7 +298,7 @@ func relayPackets() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
send(shared.BuildPkt(shared.BROADCAST_PKT, encryptedPkt))
|
||||
send(buildAuthPkt(shared.BROADCAST_PKT, encryptedPkt))
|
||||
} else {
|
||||
destSessionKey := getOrEstablishSessionKey(destIP)
|
||||
|
||||
@@ -288,12 +307,18 @@ func relayPackets() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reqBody := append(net.ParseIP(destIP), append(internalIP, encryptedPkt...)...)
|
||||
send(shared.BuildPkt(shared.ENC_PKT, reqBody))
|
||||
send(buildAuthPkt(shared.ENC_PKT, net.ParseIP(destIP), internalIP, encryptedPkt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func buildAuthPkt(pktType uint16, parts ...[]byte) []byte {
|
||||
pkt := shared.BuildPkt(pktType, parts...)
|
||||
mac := hmac.New(sha256.New, authSecret)
|
||||
mac.Write(pkt[4:])
|
||||
return append(pkt[:4], append(mac.Sum(nil), pkt[4:]...)...)
|
||||
}
|
||||
|
||||
func send(req []byte) {
|
||||
if _, err := conn.WriteToUDP(req, serverAddr); err != nil {
|
||||
panic(err)
|
||||
|
||||
Reference in New Issue
Block a user