From 89a68a4c22ffe717f82cc40de6c16900a4121511 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 19 Jul 2021 14:11:42 -0700 Subject: [PATCH] control/noise: include the protocol version in the Noise prologue. Signed-off-by: David Anderson --- control/noise/handshake.go | 10 +++++++--- control/noise/interop_test.go | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/control/noise/handshake.go b/control/noise/handshake.go index 45086bd9a..6b163b6d9 100644 --- a/control/noise/handshake.go +++ b/control/noise/handshake.go @@ -24,7 +24,12 @@ import ( const ( protocolName = "Noise_IK_25519_ChaChaPoly_BLAKE2s" - invalidNonce = ^uint64(0) + // protocolVersion is the version string that gets included as the + // Noise "prologue" in the handshake. It exists so that we can + // ensure that peer have agreed on the protocol version they're + // executing, to defeat some MITM protocol downgrade attacks. + protocolVersion = "Tailscale Control Protocol v1" + invalidNonce = ^uint64(0) ) // Client initiates a Noise client handshake, returning the resulting @@ -227,8 +232,7 @@ func (s *symmetricState) Initialize() { s.k = [chp.KeySize]byte{} s.n = invalidNonce s.mixer = newBLAKE2s() - // Mix in an empty prologue. - s.MixHash(nil) + s.MixHash([]byte(protocolVersion)) } // MixHash updates s.h to be BLAKE2s(s.h || data), where || is diff --git a/control/noise/interop_test.go b/control/noise/interop_test.go index 7f9b0926a..05fe6805d 100644 --- a/control/noise/interop_test.go +++ b/control/noise/interop_test.go @@ -120,7 +120,7 @@ func noiseExplorerClient(conn net.Conn, controlKey key.Public, machineKey key.Pr private_key: machineKey, public_key: machineKey.Public(), } - session := InitSession(true, nil, mk, controlKey) + session := InitSession(true, []byte(protocolVersion), mk, controlKey) _, msg1 := SendMessage(&session, nil) if _, err := conn.Write(msg1.ne[:]); err != nil { @@ -182,7 +182,7 @@ func noiseExplorerServer(conn net.Conn, controlKey key.Private, wantMachineKey k private_key: controlKey, public_key: controlKey.Public(), } - session := InitSession(false, nil, mk, [32]byte{}) + session := InitSession(false, []byte(protocolVersion), mk, [32]byte{}) var buf [1024]byte if _, err := io.ReadFull(conn, buf[:96]); err != nil {