commit d7459bb81473fa6454c20bb2c1b24744c7bd954f Author: Philipp Winter phw@torproject.org Date: Sun Dec 28 17:28:51 2014 +0100
Fix replay protection.
The server must also cache the HMAC of its own UniformDH messages. Otherwise, an active adversary could replay the server's UniformDH message and evade the replay protection. --- ChangeLog | 2 ++ obfsproxy/transports/scramblesuit/scramblesuit.py | 3 ++- obfsproxy/transports/scramblesuit/uniformdh.py | 7 ++++++- 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/ChangeLog b/ChangeLog index 7d66351..3107d2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,8 @@ Changes in version 0.2.13 - UNRELEASED: - Correctly handle the ScrambleSuit password being missing entirely when running in managed mode. Patch by Yawning Angel. Fixes #13587. + - Make ScrambleSuit servers cache the HMAC of their own UniformDH messages. + Fixes #14038.
Changes in version 0.2.12 - 2014-07-22: diff --git a/obfsproxy/transports/scramblesuit/scramblesuit.py b/obfsproxy/transports/scramblesuit/scramblesuit.py index 3f93b1d..40706b9 100644 --- a/obfsproxy/transports/scramblesuit/scramblesuit.py +++ b/obfsproxy/transports/scramblesuit/scramblesuit.py @@ -516,7 +516,8 @@ class ScrambleSuitTransport( base.BaseTransport ): elif self.uniformdh.receivePublicKey(data, self.deriveSecrets, self.srvState): # Now send the server's UniformDH public key to the client. - handshakeMsg = self.uniformdh.createHandshake() + handshakeMsg = self.uniformdh.createHandshake(srvState= + self.srvState)
log.debug("Sending %d bytes of UniformDH handshake and " "session ticket." % len(handshakeMsg)) diff --git a/obfsproxy/transports/scramblesuit/uniformdh.py b/obfsproxy/transports/scramblesuit/uniformdh.py index dd16070..a9e5662 100644 --- a/obfsproxy/transports/scramblesuit/uniformdh.py +++ b/obfsproxy/transports/scramblesuit/uniformdh.py @@ -156,7 +156,7 @@ class UniformDH( object ):
return handshake[:const.PUBLIC_KEY_LENGTH]
- def createHandshake( self ): + def createHandshake( self, srvState=None ): """ Create and return a ready-to-be-sent UniformDH handshake.
@@ -195,6 +195,11 @@ class UniformDH( object ): mac = mycrypto.HMAC_SHA256_128(self.sharedSecret, publicKey + padding + mark + epoch)
+ if self.weAreServer and (srvState is not None): + log.debug("Adding the HMAC authenticating the server's UniformDH " + "message to the replay table: %s." % mac.encode('hex')) + srvState.registerKey(mac) + return publicKey + padding + mark + mac
# Alias class name in order to provide a more intuitive API.