summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJeff Forcier <jeff@bitprophet.org>2014-02-14 11:53:59 -0800
committerJeff Forcier <jeff@bitprophet.org>2014-02-14 11:53:59 -0800
commit4e9af2f7ca91613ea4c60ca22b96adc2247b1ba2 (patch)
tree7867d5d252825df16830e4aed09ad79ab2f089ec
parent4a5f007c029cfabac35161d8147d616c79009bd8 (diff)
parent30518280f1356465f0acfdb4816843b61303a633 (diff)
Merge branch '1.10' into 1.11
Conflicts: sites/www/changelog.rst
-rw-r--r--paramiko/hostkeys.py4
-rw-r--r--paramiko/packet.py2
-rw-r--r--paramiko/util.py9
-rw-r--r--sites/www/changelog.rst4
4 files changed, 16 insertions, 3 deletions
diff --git a/paramiko/hostkeys.py b/paramiko/hostkeys.py
index f967a3da..c34b1738 100644
--- a/paramiko/hostkeys.py
+++ b/paramiko/hostkeys.py
@@ -28,7 +28,7 @@ import UserDict
from paramiko.common import *
from paramiko.dsskey import DSSKey
from paramiko.rsakey import RSAKey
-from paramiko.util import get_logger
+from paramiko.util import get_logger, constant_time_bytes_eq
class InvalidHostKey(Exception):
@@ -243,7 +243,7 @@ class HostKeys (UserDict.DictMixin):
entries = []
for e in self._entries:
for h in e.hostnames:
- if (h.startswith('|1|') and (self.hash_host(hostname, h) == h)) or (h == hostname):
+ if h.startswith('|1|') and constant_time_bytes_eq(self.hash_host(hostname, h), h) or h == hostname:
entries.append(e)
if len(entries) == 0:
return None
diff --git a/paramiko/packet.py b/paramiko/packet.py
index 6ab7363d..af807956 100644
--- a/paramiko/packet.py
+++ b/paramiko/packet.py
@@ -357,7 +357,7 @@ class Packetizer (object):
mac = post_packet[:self.__mac_size_in]
mac_payload = struct.pack('>II', self.__sequence_number_in, packet_size) + packet
my_mac = compute_hmac(self.__mac_key_in, mac_payload, self.__mac_engine_in)[:self.__mac_size_in]
- if my_mac != mac:
+ if not util.constant_time_bytes_eq(my_mac, mac):
raise SSHException('Mismatched MAC')
padding = ord(packet[0])
payload = packet[1:packet_size - padding]
diff --git a/paramiko/util.py b/paramiko/util.py
index 85ee6b06..9db512de 100644
--- a/paramiko/util.py
+++ b/paramiko/util.py
@@ -309,3 +309,12 @@ class Counter (object):
def new(cls, nbits, initial_value=1L, overflow=0L):
return cls(nbits, initial_value=initial_value, overflow=overflow)
new = classmethod(new)
+
+
+def constant_time_bytes_eq(a, b):
+ if len(a) != len(b):
+ return False
+ res = 0
+ for i in xrange(len(a)):
+ res |= ord(a[i]) ^ ord(b[i])
+ return res == 0
diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst
index efd6610b..9d41cb22 100644
--- a/sites/www/changelog.rst
+++ b/sites/www/changelog.rst
@@ -2,6 +2,10 @@
Changelog
=========
+* :bug:`-` Use constant-time hash comparison operations where possible, to
+ protect against `timing-based attacks
+ <http://codahale.com/a-lesson-in-timing-attacks/>`_. Thanks to Alex Gaynor
+ for the patch.
* :release:`1.11.4 <2014-02-14>`
* :release:`1.10.6 <2014-02-14>`
* :bug:`252` (`Fabric #1020 <https://github.com/fabric/fabric/issues/1020>`_)