From 7efb8cc2c49fe14cfd4edc127b108e6d2f6058f7 Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Fri, 17 Nov 2023 13:37:11 -0800 Subject: [PATCH] Fixes to negotiate/accept cipher remodulation --- xs/xs.go | 15 +++++++++------ xsd/xsd.go | 21 +++++++++++++++++---- xsnet/net.go | 15 +++++++++------ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/xs/xs.go b/xs/xs.go index dc440d2..382e158 100755 --- a/xs/xs.go +++ b/xs/xs.go @@ -702,7 +702,7 @@ func main() { //nolint: funlen, gocyclo cmdStr string tunSpecStr string // lport1:rport1[,lport2:rport2,...] rekeySecs uint - remodulate bool // true: when rekeying, switch to random cipher/hmac alg + remodRequested bool // true: when rekeying, switch to random cipher/hmac alg copySrc []byte copyDst string copyQuiet bool @@ -748,7 +748,7 @@ func main() { //nolint: funlen, gocyclo flag.StringVar(&kcpMode, "K", "unused", "KCP `alg`, one of [KCP_NONE | KCP_AES | KCP_BLOWFISH | KCP_CAST5 | KCP_SM4 | KCP_SALSA20 | KCP_SIMPLEXOR | KCP_TEA | KCP_3DES | KCP_TWOFISH | KCP_XTEA] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP") //nolint:lll flag.UintVar(&port, "p", 2000, "``port") //nolint:gomnd,lll flag.UintVar(&rekeySecs, "r", 300, "rekey interval in `secs`") - flag.BoolVar(&remodulate, "R", false, "Borg Countermeasures (remodulate cipher/hmac alg on each rekey)") + flag.BoolVar(&remodRequested, "R", false, "Borg Countermeasures (remodulate cipher/hmac alg on each rekey)") //nolint:gocritic,nolintlint // flag.StringVar(&authCookie, "a", "", "auth cookie") flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts") flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min `msecs`") //nolint:gomnd @@ -969,15 +969,18 @@ func main() { //nolint: funlen, gocyclo if kcpMode != "unused" { proto = "kcp" } - conn, err := xsnet.Dial(proto, server, cipherAlg, hmacAlg, kexAlg, kcpMode) + + remodExtArg := "" + if remodRequested { + remodExtArg = "-R" + } + // Pass opt to Dial() via extensions arg + conn, err := xsnet.Dial(proto, server, cipherAlg, hmacAlg, kexAlg, kcpMode, remodExtArg) if err != nil { fmt.Println(err) exitWithStatus(XSNetDialFailed) } - if remodulate { - conn.SetOpts(xsnet.CORemodulateShields) - } conn.RekeyHelper(rekeySecs) defer conn.ShutdownRekey() diff --git a/xsd/xsd.go b/xsd/xsd.go index b682141..70f956b 100755 --- a/xsd/xsd.go +++ b/xsd/xsd.go @@ -530,13 +530,13 @@ func main() { //nolint:funlen,gocyclo var dbg bool var laddr string var rekeySecs uint - var remodulate bool // true: when rekeying, switch to random cipher/hmac alg + var remodSupported bool // true: when rekeying, switch to random cipher/hmac alg var useSystemPasswd bool flag.BoolVar(&vopt, "v", false, "show version") flag.UintVar(&rekeySecs, "r", 300, "rekey interval in `secs`") - flag.BoolVar(&remodulate, "R", false, "Borg Countermeasures (remodulate cipher/hmac alg on each rekey)") + flag.BoolVar(&remodSupported, "R", false, "Borg Countermeasures (remodulate cipher/hmac alg on each rekey)") flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen") //nolint:gomnd,lll flag.StringVar(&kcpMode, "K", "unused", `set to one of ["KCP_NONE","KCP_AES", "KCP_BLOWFISH", "KCP_CAST5", "KCP_SM4", "KCP_SALSA20", "KCP_SIMPLEXOR", "KCP_TEA", "KCP_3DES", "KCP_TWOFISH", "KCP_XTEA"] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP`) //nolint:lll flag.BoolVar(&useSysLogin, "L", false, "use system login") @@ -704,8 +704,21 @@ func main() { //nolint:funlen,gocyclo } else { log.Println("Accepted client") - if remodulate { - conn.SetOpts(xsnet.CORemodulateShields) + // Only enable cipher alg changes on re-key if we were told + // to support it (launching xsd with -R), *and* the client + // proposes to use it. + if !remodSupported { + if (conn.Opts() & xsnet.CORemodulateShields) != 0 { + logger.LogDebug("[client proposed -R, but we don't support it.]") + conn.Close() + continue + } + } else { + if conn.Opts()&xsnet.CORemodulateShields != 0 { + logger.LogDebug("[cipher remodulation active]") + } else { + logger.LogDebug("[cipher remodulation inactive]") + } } conn.RekeyHelper(rekeySecs) diff --git a/xsnet/net.go b/xsnet/net.go index 8253886..f09d92c 100644 --- a/xsnet/net.go +++ b/xsnet/net.go @@ -241,7 +241,7 @@ func (hc *Conn) SetConnOpts(copts uint32) { // // Consumers of this lib may use this for protocol-level options not part // of the KEx or encryption info used by the connection. -func (hc Conn) Opts() uint32 { +func (hc *Conn) Opts() uint32 { return hc.opts } @@ -363,8 +363,11 @@ func (hc *Conn) applyConnExtensions(extensions ...string) { log.Println("[extension arg = H_SHA512]") hc.cipheropts &= (0xFFFF00FF) hc.cipheropts |= (HmacSHA512 << 8) - //default: - // log.Printf("[Dial ext \"%s\" ignored]\n", s) + case "-R": + log.Println("[extension arg = -R]") + hc.opts |= CORemodulateShields + //default: + // log.Printf("[Dial ext \"%s\" ignored]\n", s) } } } @@ -1351,7 +1354,7 @@ func (hc *Conn) Read(b []byte) (n int, err error) { //logger.LogDebug(fmt.Sprintf("[Got rekey [%02x %02x %02x ...]\n", // payloadBytes[0], payloadBytes[1], payloadBytes[2])) rekeyData := payloadBytes - if hc.opts&CORemodulateShields != 0 { + if (hc.opts & CORemodulateShields) != 0 { hc.cipheropts = getNewStreamAlgs(rekeyData[0], rekeyData[1]) } hc.r, hc.rm, err = hc.getStream(rekeyData) @@ -1615,10 +1618,10 @@ func (hc *Conn) RekeyHelper(intervalSecs uint) { _, err := crand.Read(rekeyData) //logger.LogDebug(fmt.Sprintf("[rekey [%02x %02x %02x ...]\n", // rekeyData[0], rekeyData[1], rekeyData[2])) - //logger.LogDebug("[+rekeyHelper]") + logger.LogDebug("[+rekeyHelper]") _, err = hc.WritePacket(rekeyData, CSORekey) hc.Lock() - if hc.opts&CORemodulateShields != 0 { + if (hc.opts & CORemodulateShields) != 0 { hc.cipheropts = getNewStreamAlgs(rekeyData[0], rekeyData[1]) } hc.w, hc.wm, err = hc.getStream(rekeyData)