Browse Source

Allow overriding the KEX method(s) from the command line.

Yawning Angel 4 years ago
parent
commit
47c14b1cfc
4 changed files with 94 additions and 23 deletions
  1. 3 1
      basket2proxy/client.go
  2. 53 1
      basket2proxy/main.go
  3. 2 11
      basket2proxy/server.go
  4. 36 10
      handshake/handshake.go

+ 3 - 1
basket2proxy/client.go

@@ -71,7 +71,7 @@ func (s *clientState) parseBridgeArgs(args *pt.Args) (*basket2.ClientConfig, err
 	}
 	for _, m := range kexMethods {
 		method := handshake.KEXMethod(m)
-		if handshake.IsSupportedMethod(method) {
+		if isEnabledKEXMethod(method) {
 			cfg.KEXMethod = method
 			break
 		}
@@ -126,6 +126,8 @@ func (s *clientState) connHandler(socksConn *pt.SocksConn) error {
 	}
 	cfg.PaddingMethods = append(cfg.PaddingMethods, defaultPaddingMethods...)
 
+	log.Debugf("%s: Using KEX: %s", addrStr, cfg.KEXMethod.ToString())
+
 	// Intialize the basket2 state.
 	bConn, err := basket2.NewClientConn(cfg)
 	if err != nil {

+ 53 - 1
basket2proxy/main.go

@@ -26,12 +26,14 @@ import (
 	"net"
 	"os"
 	"path"
+	"strings"
 	"sync"
 	"syscall"
 
 	"git.schwanenlied.me/yawning/basket2.git"
 	"git.schwanenlied.me/yawning/basket2.git/basket2proxy/internal/log"
 	"git.schwanenlied.me/yawning/basket2.git/basket2proxy/internal/ptextras"
+	"git.schwanenlied.me/yawning/basket2.git/handshake"
 	"git.torproject.org/pluggable-transports/goptlib.git"
 )
 
@@ -54,8 +56,19 @@ var (
 	defaultPaddingMethods = []basket2.PaddingMethod{
 		basket2.PaddingNull,
 	}
+
+	enabledKEXMethods []handshake.KEXMethod
 )
 
+func isEnabledKEXMethod(m handshake.KEXMethod) bool {
+	for _, v := range enabledKEXMethods {
+		if m == v {
+			return true
+		}
+	}
+	return false
+}
+
 func getVersion() string {
 	return "basket2proxy - " + basket2proxyVersion
 }
@@ -106,20 +119,59 @@ func copyLoop(bConn, orConn net.Conn, addrStr string) {
 	}
 }
 
+func overrideKEXMethods(s string) error {
+	if s == "" {
+		return nil
+	}
+
+	var methods []handshake.KEXMethod
+	for _, mStr := range strings.Split(s, ",") {
+		m := handshake.KEXMethodFromString(mStr)
+		if m == handshake.KEXInvalid {
+			return handshake.ErrInvalidKEXMethod
+		}
+		methods = append(methods, m)
+	}
+	if len(methods) == 0 {
+		return fmt.Errorf("no valid KEX methods provided")
+	}
+
+	enabledKEXMethods = methods
+	return nil
+}
+
 func main() {
 	termMon = ptextras.NewTermMonitor()
 	_, execName := path.Split(os.Args[0])
 
 	// Parse and act on the command line arguments.
-	showVersion := flag.Bool("version", false, "Show version and exit.")
+	showVersion := flag.Bool("version", false, "Show version and exit")
 	enableLogging := flag.Bool("enableLogging", false, "Log to TOR_PT_STATE_LOCATION/"+basket2proxyLogFile)
 	logLevelStr := flag.String("logLevel", "ERROR", "Log level (ERROR/WARN/INFO/DEBUG)")
+	showAlgorithms := flag.Bool("algorithms", false, "Show supported algorithms and exit")
+	kexMethodsStr := flag.String("kexMethods", "", "Key exchange methods")
 	flag.Parse()
 
+	// Populate the lists of supported algorithms.
+	enabledKEXMethods = handshake.SupportedKEXMethods()
+
 	if *showVersion {
 		fmt.Printf("%s\n", getVersion())
 		os.Exit(0)
 	}
+	if *showAlgorithms {
+		fmt.Printf("%s\n", getVersion())
+		fmt.Printf("\n Key Exchange Methods:\n")
+		for _, m := range enabledKEXMethods {
+			fmt.Printf("  %s - %s\n", m.ToHexString(), m.ToString())
+		}
+		os.Exit(0)
+	}
+
+	// XXX: Support for overriding the padding algorithms etc.
+	if err := overrideKEXMethods(*kexMethodsStr); err != nil {
+		golog.Fatalf("%s: [ERROR]: Failed to set KEX methods: %v", err)
+	}
 
 	// Common PT initialization (primarily for the stateDir).
 	isClient, err := ptextras.IsClient()

+ 2 - 11
basket2proxy/server.go

@@ -46,14 +46,7 @@ const (
 	maxCloseDelay          = 60
 )
 
-var (
-	defaultKEXMethods = []handshake.KEXMethod{
-		handshake.X25519NewHope,
-		handshake.X448NewHope,
-	}
-
-	useLargeReplayFilter bool
-)
+var useLargeReplayFilter bool
 
 type serverState struct {
 	config *basket2.ServerConfig
@@ -266,11 +259,9 @@ func initServerListener(si *pt.ServerInfo, bindaddr *pt.Bindaddr) (net.Listener,
 	cfg := &basket2.ServerConfig{
 		ServerPrivateKey: sk,
 		ReplayFilter:     rf,
+		KEXMethods:       enabledKEXMethods,
 	}
 	// XXX: Override the default values.
-	if len(cfg.KEXMethods) == 0 {
-		cfg.KEXMethods = append(cfg.KEXMethods, defaultKEXMethods...)
-	}
 	if len(cfg.PaddingMethods) == 0 {
 		cfg.PaddingMethods = append(cfg.PaddingMethods, defaultPaddingMethods...)
 	}

+ 36 - 10
handshake/handshake.go

@@ -66,7 +66,12 @@ var (
 	handshakeKdfTweak = []byte("basket2-handshake-v1-kdf-tweak")
 	newhopeRandTweak  = []byte("basket2-newhope-tweak")
 
-	supportedMethods map[KEXMethod]bool
+	// Note: Ordering matters here, so specify the non-tinfoil hat option
+	// first since it's adequate for all but the most paranoid.
+	supportedKEXMethods = []KEXMethod{
+		X25519NewHope,
+		X448NewHope,
+	}
 )
 
 // ToHexString returns the hexdecimal string representation of a KEX method.
@@ -74,6 +79,30 @@ func (m KEXMethod) ToHexString() string {
 	return fmt.Sprintf("%02x", m)
 }
 
+// ToString returms the descriptive string reppresentaiton of a KEX method.
+func (m KEXMethod) ToString() string {
+	switch m {
+	case X25519NewHope:
+		return "X25519NewHope"
+	case X448NewHope:
+		return "X448NewHope"
+	default:
+		return "[Unknown algorithm]"
+	}
+}
+
+// KEXMethodFromString returns the KEXMethod corresponding to a given string.
+func KEXMethodFromString(s string) KEXMethod {
+	switch s {
+	case "X25519NewHope":
+		return X25519NewHope
+	case "X448NewHope":
+		return X448NewHope
+	default:
+		return KEXInvalid
+	}
+}
+
 // SessionKeys is the handshake output.  It is safe to assume contributatory
 // behavior from both parties in the KDF output and the handshake transcript
 // digest, as points of small order are explicitly rejected.
@@ -301,13 +330,10 @@ func NewServerHandshake(rand io.Reader, kexMethods []KEXMethod, replay ReplayFil
 	return s, nil
 }
 
-// IsSupportedMethod returns true iff the KEX method is supported.
-func IsSupportedMethod(m KEXMethod) bool {
-	return supportedMethods[m]
-}
-
-func init() {
-	supportedMethods = make(map[KEXMethod]bool)
-	supportedMethods[X25519NewHope] = true
-	supportedMethods[X448NewHope] = true
+// SupportedKEXMethods returns the list of supported KEX methods in order of
+// preference.
+func SupportedKEXMethods() []KEXMethod {
+	var ret []KEXMethod
+	ret = append(ret, supportedKEXMethods...)
+	return ret
 }